Javaでオブジェクトを比較するときは、セマンティックチェックを行い、オブジェクトのタイプを比較して状態を識別します。
- 自体(同じインスタンス)
- 自体(クローン、または再構築されたコピー)
- 異なるタイプの他のオブジェクト
- 同じタイプの他のオブジェクト
- null
ルール:
- 対称性:a.equals(b) == b.equals(a)
- equals()常に利回り- trueまたは- false、決して- NullpointerException、- ClassCastExceptionまたは任意の他のスロー可能
比較:
- 型チェック:両方のインスタンスは同じ型である必要があります。つまり、実際のクラスが等しいかどうかを比較する必要があります。開発者instanceofが型の比較に使用する場合、これは正しく実装されないことがよくあります(サブクラスがない場合にのみ機能し、の場合は対称規則に違反しA extends B -> a instanceof b != b instanceof a)ます)。
- 状態を識別するセマンティックチェック:インスタンスが識別される状態を理解するようにしてください。人は、社会保障番号で識別できますが、髪の色(染色可能)、名前(変更可能)、または年齢(常に変更)では識別できません。値オブジェクトの場合のみ、完全な状態(すべての非一時フィールド)を比較する必要があります。それ以外の場合は、インスタンスを識別するものだけを確認してください。
あなたのPersonクラス:
public boolean equals(Object obj) {
    // same instance
    if (obj == this) {
        return true;
    }
    // null
    if (obj == null) {
        return false;
    }
    // type
    if (!getClass().equals(obj.getClass())) {
        return false;
    }
    // cast and compare state
    Person other = (Person) obj;
    return Objects.equals(name, other.name) && Objects.equals(age, other.age);
}
再利用可能な汎用ユーティリティクラス:
public final class Equals {
    private Equals() {
        // private constructor, no instances allowed
    }
    /**
     * Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state
     *
     * @param instance       object instance (where the equals() is implemented)
     * @param other          other instance to compare to
     * @param stateAccessors stateAccessors for state to compare, optional
     * @param <T>            instance type
     * @return true when equals, false otherwise
     */
    public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) {
        if (instance == null) {
            return other == null;
        }
        if (instance == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!instance.getClass().equals(other.getClass())) {
            return false;
        }
        if (stateAccessors == null) {
            return true;
        }
        return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other)));
    }
}
あなたのためにPersonクラス、このユーティリティクラスを使用しました:
public boolean equals(Object obj) {
    return Equals.as(this, obj, t -> t.name, t -> t.age);
}