スッキリわかるJava入門 実践編 第３版 まとめ - part1 -インスタンスの基本操作

#はじめに
こんにちは　◤●ㅅ●◥ﾉ
入門編に続いて実践編のアウトプットとして記事を書いて行こうと思います！

今回はインスタンスの基本機能について学びました！

## 第１章　インスタンスの基本操作
Javaでは自分でたくさんのクラスを作る必要があります
⇨すべてのクラスについて共通して利用できる汎用的な仕組みが用意されています
　⇨すべての開発シーンで手助けしてくれるインスタンスの基本機能について学んでいきます

### 1.インスタンスの５大基本操作
:thinking:そもそもインスタンスとは？
　クラスという型から作り出された実体のこと

Javaにおけるすべてのクラスは継承関係を親へ辿っていくとJava.lang.Objectに行き着く
:star:Objectクラスがあることのメリット
1.すべてのクラスはObjectクラスで定義されたメソッドを持つことが保証される
2.Object型変数には、あらゆるインスタンスを代入可能

多くのインスタンスに共通する５つの操作
![スクリーンショット 2023-09-12 11.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336192/576d3962-95f5-6831-ed84-06d0bb914f2d.png)

### 2.インスタンスの文字列表現

#### toString()の責務
　インスタンスの内容を人が呼んで理解できる文字列で表現したもので返す

すべてのインスタンスがtoStringを持っているためインスタンスの中身を知りたい時
　⇨toString()を呼び出すことで知ることができる

よく使われるSystem.out.println()命令
引数にインスタンスを渡すとそのtoString()を呼び出し文字列表現を取り出し、画面に表示する

#### :rolling_eyes:注意点
あるクラスがどのような文字列表現を返すかは開発者にしかわからない
⇨新たにクラスを作ったら自分で不適切なtoStirng()をオーバーライドする必要がある

### 3.インスタンスの等価判定

#### equals()の責務
　２つの変数に入っているインスタンスを比較して等価であるかを判定する

#### 似ている概念"等値"との違い
似たような概念である等値とは全く別のもの
　等価(equals)　指している２つのものが同じ内容である
　等値( == )　 　指しているものが完全に同一の存在である

#### 比較の判断基準
判断者はJVM

==演算子を用いる等値判定←簡単
　２つの変数の指し示すアドレスが同じであるかを単純に比較するだけ

equals()を用いる等価判定←難しい
　「２つのインスタンスの何をもって同一とみなすか」という基準がクラスによってまちまち
　⇨判断基準を持っているのは開発者のみ

#### equals()のオーバーライド
「何をもってインスタンス同士を等価とみなすか」判断できるのは開発者だけ
　⇨自分のクラスを開発したらオーバーライドすることで開発者が
　　　適切と考える等価判定アルゴリズムをJVMに伝えるべきである

equals()を正しくオーバーライドしていないクラスをコレクションに格納すると誤作動につながる

### 4.インスタンスの要約
equals()を正しくオーバーライドしていても誤作動になってしまうことがある
　⇨Hash系のコレクションを使う場合では誤動作してしまうことがある

#### HashSetの内部動作
HashSetは各要素にequals()を使って聞いてまわることはしない
⇨equals()による等価判定は比較的大きな計算コストがかかる

Hash系のコレクションクラスでは
1.高速で、あいまいな方法で、各要素に「だいたい同じか？」問い合わせる
2.「だいたい同じ」な要素にだけ、equals()で「厳密に同じか？」問い合わせる
という２段階の方式で目的の要素を探し出している

「だいたい同じか？」の判定
　⇨ハッシュ値というものを使う

ハッシュ値...そのインスタンスの内容を数値として要約したもの
　　　　　　以下のルールに従っていればどのような方法で算出しても大丈夫

:star: ハッシュ値の条件
・同じ（等価）インスタンスからは、必ず同じハッシュ値が得られること
・異なるインスタンスからは、なるべく異なるハッシュ値が得られること

#### hashCode()の責務
　すべてのインスタンスに「ハッシュ値の条件」に従った値を返す

#### hashCode()のオーバーライド
　クラスを開発する私たち自身がhashCode()を正しくオーバーライドする必要がある

### 5.インスタンスの順序付け
あるクラスについて一般的に想定される並べ順のこと...自然順序付け

自然順序を宣言するには
⇨java.lang.Comparableインターフェースを実装する
　⇨このインターフェースを実装するとcompareTo()のオーバーライドが強制される

#### compareTo()の責務
　引数で渡されてきたインスタンスobjと自分自身とを比較してその大小関係を判定する

具体的な値の返し方
・自分自身の方がobjより小さいとき...負の数
・自分自身とobjとが等しい場合...0
・自分自身の方がobjよりも大きいとき...正の数

:star: Comparableを実装して便利に
開発するクラスに自然順序を定められるなら
Comparableを実装しておくことで並び替えが便利に行える

#### コンパレータの利用
引数として渡されたコレクションを自然順序で並び替えてくれるCollections.sort()
:pencil2: Collections.sort()の２つの使い方
1.自然順序で並び替える
`Collections.sort(list)`
2.第２引数に指定された順で並び替える
`Collections.sort(list, cmp)`

コンパレータ...現実世界における「並び替えのルール」をクラスとして表現したもの
java.util.Comparatorインタフェースを実装し、
唯一のメソッドであるcompare()をオーバーライドして定義する決まり

### 6.インスタンスの複製
インスタンスをコピーする必要がある時に複製を作っておき、
それを引数や戻り値として引き渡すテクニック...防御的コピー

インスタンスをコピーするための標準機能がJavaには備わっている

:thinking:代入でコピーはできないのか？
アドレス情報（参照）がコピーされるだけで、インスタンスの実体は１つのままになっている

インスタンスの複製には
1.new演算子を用いて別のインスタンスを作成し、コピー先に入れる
2.コピー元のすべてのフィールド内容をコピー先へコピーする
という手順を踏む必要がある

#### clone()メソッドの責務
インスタンスの複製のために1.2.の手順を踏むのはめんどくさい
⇨すべてのクラスは「自分自身の複製インスタンスを作って返す」責務を持ったclone()を継承する

#### clone()の実装
1.Cloneableインタフェースを実装する
　clone()による複製をサポートしていることを外部に表明するために
　java.lang.Cloneableインタフェースを実装する

2.clone()をpublicでオーバーライドする
cloneをpublicでオーバーライドして外部から呼び出す

Cloneableはclone()を定義していない
Cloneableは「clone()を実装することによって複製に対応していることを表明するため」
だけに存在している
⇨このような目的で利用する特殊なインターフェースを特にマーカーインターフェースと呼ぶ

#### コピーの種類
・浅いコピー...そのインスタンスのみを複製する
・深いコピー...そのインスタンスが参照しているインスタンスを含めて複製する

## まとめ
Objectの３つの基本操作
・toString()をオーバーライドして文字列表現を定義できる
・equals()をオーバーライドして意味的に正しく等価を判定できるようにする必要がある
・hashCode()を正しくオーバーライドしてハッシュ値を用いたクラスを利用できる
順序付け
・Comparableインターフェースを実装することで自然順序付けを定義できる
・Comparatorインターフェースを実装することで自然順序以外の並び順を定義できる
複製
・Cloneableインタフェースを実装してclone()をオーバーライドすることで容易に複製できる