Item 10 - equals는 일반 규약을 지켜 재정의하라
equals
메서드는 재정의하기 쉬워보이지만 곳곳에 함정이 도사리고 있다.
따라서 재정의가 필요하지 않은 경우에는 재정의하지 않는 것이 최선의 선택이다.
equals 재정의를 추천하지 않는 상황 🙅
- 각 인스턴스가 본질적으로 고유한 경우
- 값을 표현하는게 아니라 동작하는 개체를 표현하는 클래스 일 때 ex) Thread 클래스
- 인스턴스의 ‘논리적 동치성’을 검사할 일이 없는 경우
- 상위 클래스에서 재정의한 equals가 하위 클래스에도 들어맞는 경우
- 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없는 경우
equals 규약
- 반사성: A.equals(A) == true
- 대칭성: A.equals(B) == B.equals(A)
- CaseInsensitiveString
- 추이성: A.equals(B) && B.equals(C), A.equals(C)
- Point, ColorPoint(inherit), CounterPointer, ColorPoint(comp)
- 일관성: A.equals(B) == A.equals(B)
- null-아님: A.equals(null) == false
양질의 equals 메서드 구현 방법 👍
==
연산자를 사용해 입력이 자기 자신의 참조인지 확인한다. - 성능 최적화instanceof
연산자로 입력이 올바른 타입인지 확인한다.- 입력된 값을 올바른 타입으로 형변환 한다.
- 입력 객체와 자기 자신의 대응되는 핵심 필드가 일치하는지 확인한다.
- 구글의
AutoValue
또는 Lombok을 사용한다. - IDE의 코드 생성 기능을 사용한다.
주의사항 🚑
- equals를 재정의 할 때 hashCode도 반드시 재정의하자. (아이템 11)
- 너무 복잡하게 해결하지 말자.
- Object가 아닌 타입의 매개변수를 받는 equals 메서드는 선언하지 말자.
핵심 정리 💡
- 꼭 필요한 경우가 아니면 equals를 재정의하지 말자.
- 재정의해야 할 때는 그 클래스의 핵심 필드를 빠짐없이 규약을 지켜가면서 비교하자.
참고 🕶️
This post is licensed under CC BY 4.0 by the author.