LoginSignup
1
3

More than 3 years have passed since last update.

==(同一性)とequalsメソッド(同値性)の違い、オーバーライドしよう

Last updated at Posted at 2020-08-05

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が新たにインスタンスを生成し、s0s1は違うインスタンスになった。

equalsメソッド(同値性)

equalsメソッドは、同値であることを判定する。つまり、インスタンスはことなるが、同じ値を持っているか判定する。

デフォルトのObjectクラスに定義されているequalsメソッドは、

public boolean equals(Object obj){
  return (this == obj);
}

と定義されており、同一性を確認する仕様になっているため、

オーバーライドして使用することを前提としている。

さらに!!

equalsメソッドをオーバーライドする時は、セットでhashCodeもオーバーライドしないといけない。
※ hashCodeとは、インスタンスが持っている値をハッシュ関数に変換して、確認できるメソッド

Object(Java SE 11 & JDK 11)

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も違う値が出力されている。

1
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3