반응형
아이템 11 : equals를 재정의하거든 hasCode도 재정의하라
equales를 재정의한 모든 클래스에서 hashCode도 재정의해야 한다.
다음은 Object 명세에서 발췌한 규약이다.
- equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다.
- equals(Object)가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다.
- equals(Object)가 두 객체를 다르다고 판단했더라도, 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다, 단, 다른 객체에 대해서는 다른 값을 반환해야 해시테이블의 성능이 좋아진다.
hashCode 재정의를 잘못했을 때 크게 문제가 되는 조항은 두 번째다. 즉, 논리적으로 같은 객체는 같은 해시코드를 반환해야 한다.
클래스가 불변이고 해시코드를 계산하는 비용이 크다면, 매번 새로 계산하기 보다는 캐싱하는 방식을 고려해야 한다.
성능을 높인답시고 해시코드를 계산할 때 핵심 필드를 생략해서는 안 된다.
속도야 빨라지겠지만, 해시 품질이 나빠져 해시테이블의 성능을 심각하게 떨어 뜨릴 수도 있다.
hashCode가 반환하는 값의 생성 규칙을 API 사용자에게 자세히 공표하지 말자. 그래야 클라이언트가 이 값에 의지하지 않게 되고, 추후에 계산 방식을 바꿀 수도 있다.
핵심 정리
equals를 재정의할 때는 hashCode도 반드시 재정의해야 한다. 그렇지 않으면 프로그램이 제대로 동작하지 않을 것이다.
재정의한 hashCode는 Object의 API 문서에 기술된 일반 규약을 따라야 하며, 서로 다른 인스턴스라면 되도록 해시코드도 서로 다르게 구현해야 한다. AutoValue 프레임워크를 사용하면 equals와 hashCode를 자동으로 만들어준다. IDE들도 이런 기능을 일부 제공한다.
반응형
'언어 > JAVA' 카테고리의 다른 글
[Effective Java] clone 재정의는 주의해서 진행하라 (0) | 2020.03.15 |
---|---|
[Effective Java] toString을 항상 재정의하라 (0) | 2020.03.14 |
[Effective Java] equals는 일반 규약을 지켜 재정의하라 (0) | 2020.03.13 |
[Effective Java] try-finally보다는 try-with-resources를 사용하라 (0) | 2020.03.13 |
[Effective Java] finalizer와 cleaner 사용을 피하라 (0) | 2020.03.12 |