javaには二つの「同じ」がある。
==(同一性)
==演算子は、同一であることを判定する。つまり、複数の変数が同じインスタンスを参照していることを判定する。
A a = new A(); // A型というインスタンスを生成
A b = a; // aのインスタンスごとそのままbへコピー
System.out.println(a == b);
true
例題
public class Sample {
private int num;
public Sample(int num) {
this.num = num;
}
}
public class Main {
public static void main(String[] args) {
Sample s0 = new Sample(5); // Sample型のインスタンス生成
Sample s1 = s0; // s1にコピー
s0 = new Sample(5); // 新たにSample型インスタンス生成
System.out.println(s0 == s1);
}
}
false
Sample s1 = s0;
でコピーした時点では、同じインスタンスを持っていたが、次の行でs0
が新たにインスタンスを生成し、s0
とs1
は違うインスタンスになった。
equalsメソッド(同値性)
equalsメソッドは、同値であることを判定する。つまり、インスタンスはことなるが、同じ値を持っているか判定する。
デフォルトのObjectクラスに定義されているequalsメソッドは、
public boolean equals(Object obj){
return (this == obj);
}
と定義されており、同一性を確認する仕様になっているため、
オーバーライドして使用することを前提としている。
さらに!!
equalsメソッドをオーバーライドする時は、セットでhashCodeもオーバーライドしないといけない。
※ hashCodeとは、インスタンスが持っている値をハッシュ関数に変換して、確認できるメソッド
equals
通常、このメソッドをオーバーライドする場合は、hashCodeメソッドを常にオーバーライドして、等価なオブジェクトは等価なハッシュ・コードを保持する必要があるというhashCodeメソッドの汎用規約に従う必要があることに留意してください。
例題
public class Sample {
private int num;
private String name;
public Sample(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + num;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sample other = (Sample) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (num != other.num)
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
// 引数(num, name)が同じ
Sample a = new Sample(5, "xxx");
Sample b = new Sample(5, "xxx");
System.out.println(a.equals(b));
// それぞれのhashCodeを出力
System.out.println(a.hashCode());
System.out.println(b.hashCode());
}
}
true
3694926
3694926
equalsメソッドとhashCodeメソッドをオーバーライドしている。
もし、numかnameが一つでも違えば以下のようになる。
public class Main {
public static void main(String[] args) {
// 引数(name)が違う
Sample a = new Sample(5, "xxx");
Sample b = new Sample(5, "yyy");
System.out.println(a.equals(b));
// それぞれのhashCodeを出力
System.out.println(a.hashCode());
System.out.println(b.hashCode());
}
}
false
3694926
3725709
equals判定はfalse
になり、hashCodeも違う値が出力されている。