각 인스턴스가 본질적으로 고유하다.
값을 표현하는 경우가 아니라 동작하는 개체를 표현하는 클래스인 경우 (ex. Thread)
→ 그에 맞게 equals가 구현되어 있음
인스턴스의 논리적 동치성을 검사할 일이 없다.
상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다.
클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없다.
package-private이면 같은 패키지에서만 접근 가능하므로, 이 안에서 equals메서드를 호출할 일이 없다면 재정의할 필요가 없다는 뜻
equals가 실수로 호출되는 것을 막는 방법
@Override public boolean equals(Object e){
throw new AssertionError();
}
객체의 논리적 동치성을 확인해야 하는데 상위 클래스가 equals가 논리적 동치성을 비교하도록 재정의되어있지 않을 때
두 객체에 대한 동치 여부에 똑같이 답해야 함
잘못된 구현 예시
// 대칭성을 위반한 클래스
public final class CaseInsensitiveString{
private final String s;
public CaseInsensitiveString(String s){
this.s = Obejcts.requireNonNull(s);
}
// 대칭성 위배!
@Override public boolean equals(Object o){
if(o instanceof CaseInsensitiveString)
return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
if(o instanceof String) // 한방향으로만 작동한다.
return s.equalsIgnoreCase((String) o);
return false;
}
}
////호출하는 코드
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
cis.equals(s); // true
s.equals(cis); // false
String에서는 CaseInsensitiveString의 존재를 모르기 때문에 대칭성을 위반하게 됨
해결 방법
//대칭성을 만족하게 수정
@Override public boolean equals(Object o){
return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
→ CaseInsensitiveString 끼리만 비교하도록 한다.