はじめに
JavaSilverの学習中にて
「ふむふむ、equals()は2つのインスタンス間の同一性を判定するものなんだな」
「あれ?でもこっちには同値性を調べるって書いてる…」
「String型のequals()は親クラスのObject型のequals()を引き継いでるからデフォルトのままやろな……違うの!?なんで!?」
とまあ、概念の理解がなかなかに困難だったので備忘録としてまとめておきます。
同一性と同値性
前提知識として…
・同一性
複数の変数が同じインスタンスを参照しているどうか
下記の例だと、オブジェクト型の変数aにインスタンスaへの参照先を代入して、
オブジェクト型の変数bに変数aの中身(インスタンスaへの参照先)を代入しており、
変数は違えど参照先は同じインスタンスであるため、同一性であると言える。
Object a = new Object();
Object b = a;
System.out.println(a == b); //result:true
・同値性
異なるインスタンスでも、その中身が等しいかどうか
下記の例だと、String型のa,bは異なるインスタンスだが、
中身の値は同じであるため、同値性であるといえる。
String a = "Hello";
String b = "Hello";
System.out.println(a == b); //result:true
equals()
Objectクラスで定義されているメソッドで、デフォルトでは同一性を調べるものとなっている。
public boolean equals(Object obj){
return (this == obj)
}
ただ、ここで注意すべきなのが、equals()は本来同値性を調べるもので、
オーバーライドを用いてクラスごとに再定義するのが普通である。
JavaSilverつまずき問題
混乱したのが下記の問題(JavaSE8 Silverの黒本より)
//第3章 問12 実行結果はどうなるか
public class Main{
public static void main(String[] args){
String a = "sample";
String b = "sample";
System.out.print(a == b);
System.out.print(",");
System.out.print(a.equals(b));//result:true,true
}
}
System.out.print(a.equals(b));
のコードが「はじめに」で述べてた箇所で、
「String型のequals()は親クラスのObject型のequals()を引き継いでるからデフォルトのままやろな……違うの!?なんで!?」
に繋がります。
そのときの自分の誤った考えとしては
「えっと、equals()を呼び出して、インスタンスa, bの同値性を調べるんだよな。
あ、でもString型のequals()はObject型のequals()を引き継いでるから同一性判定なのか。
じゃあa,bは異なるインスタンスだからこれはfalseだな」
と考えた結果、答えはtrueだったので「えぇっ!?」となりました(語彙力)
(まあそもそも真ん中の行で「==」で同一性判定を行ってて、
そこがtrueだって分かったなら今回のequals()もtrueだってなりそうなもんですけどね…)
1.String型でもequals()はオーバーライドされている
「String型のequals()はObject型のequals()を引き継いでるから同一性判定なのか」
と述べていますが、半分不正解です。
Object型のequals()は同一性判定の定義となっていますが、
String型でequals()はオーバーライドされており、
2つのインスタンスが同値性の関係かを調べるものとなっています。
(コードは省略)
おわりに
1,2時間ぐらいかけて勉強しましたが、正直まだまだ理解できていない部分も多いです。
また更新します。