equals() 메서드를 재정의 하지 않고 그냥 두면 해당 클래스의 인스턴스는 오직 자기 자신하고만 같게 된다.
재정의하지 않는 것을 권장
- 각 인스턴스가 본질적으로 고유
- Thread 클래스의 equals() 가 좋은 예
- 인스턴스의 ‘논리적 동치성(logical equality)’을 검사할 일이 없다.
- 상위 클래스에서 재정의한 equals가 하위 클래스에도 맞는다.
- 예) 컬렉션 프레임워크의 구현체들은 추상클래스의 equals를 그대로 사용한다.
- equals() 를 호출할 일이 없다.
재정의해야 할 때는 언제일까?
상위 클래스의 equals가 논리적 동치성을 비교하도록 재정의 되지 않았을 때
값 클래스들이 해당됨
- Integer
- String ….. 등
재정의를 하지 않아도 될 때
싱글톤이 보장되면 equals()를 재정의 하지 않아도 된다.
- 논리적 동치성과 객체 식별성(물리적으로 같은가)이 같기 때문에
따라서 Object의 equals가 논리적 동치성까지 확인해준다고 볼 수 있다.
equals() 를 재정의할 때는 반드시 일반 규약을 따라야 함.
- 반사성(reflexivity) : null 이 아닌 모든 참조 값 x에 대해, x.equals(x) 는 true
- 대칭성(symmetry) : null 이 아닌 모든 참조 값 x, y에 대해, x.equals(y) 가 true 면 y.equals(x) 도 true
- 추이성(transitivity) : null 이 아닌 모든 참조 값 x, y, z에 대해, x.equals(y) 가 true 이고 y.equals(z) 도 true 면 x.equals(z) 도 true 다.
- 일관성(consistency) : null 이 아닌 모든 참조 값 x, y에 대해, x.equals(y)를 반복해서 호출하면 항상 true를 반환하거나 항상 false를 반환함
- null-아님 : null 이 아닌 모든 참조 값 x에 대해, x.equals(null)은 false
반사성
단순히 말하면 객체는 자기 자신과 같아야 한다
대칭성
두 객체는 서로에 대한 동치 여부에 똑같이 답해야 한다
추이성
첫 번째 객체와 두 번째 객체가 같고, 두 번째 객체와 세 번째 객체가 같다면, 첫 번째 객체와 세 번째 객체도 같다
일관성
- 두 객체가 같다면 앞으로도 영원히 같아야 한다.
- 가변 객체는 비교 시점에 따라 서로 다를 수 있지만 불변 객체는 한번 다르면 끝까지 달라야 한다.
equals의 판단에 신뢰할 수 없는 자원이 끼어 들게 해서는 안된다.
→ 항시 메모리에 존재하는 객체만을 사용해 결정적 계산만 수행해야 한다.
null-아님
모든 객체가 null과 같지 않아야 한다.
null을 명시적으로 검사하는 것보단 묵시적으로 검사하는 것이 좋다.
// 명시적 null 검사 - 필요 없다.
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
/// ,,,,,
return false;
}
// 묵시적 null 검사 - 이쪽이 더 괜찮
@Override
public boolean equals(Object obj) {
if (!(obj instanceof A)) return false;
A a = (A) obj;
/// ,,,,,
return false;
}
instanceof 연산자는 첫번째 피연산자가 null 이면 false를 반환해주기 때문에 묵시적으로 검사하는 것만으로 충분하다.
eqauls 메서드 구현 방법을 단계별로 정리
- 자기 자신의 참조인지 확인
- 프리미티브 타입은 == 연산자
- 레퍼런스 타입은 equals
- instanceof 연산자로 입력이 올바른 타입인지 확인
- 입력을 올바른 타입으로 형변환
- 입력 객체와 자기 자신의 대응되는 핵심필드들이 모두 일치하는지 하나씩 검사
어떤 필드를 먼저 비교하느냐가 equals의 성능을 좌우하기도 한다.
- 다를 가능성이 더 크거나 비교하는 비용이 싼 필드를 먼저 비교해라
- 논리적 상태와 관련 없는 필드는 비교하지 말아라
마지막 주의사항
- equals 메서드를 재정의 할 시 hashcode 도 반드시 재정의 해라
equals 메서드를 재정의 하는 행위는 꼭 필요한 경우가 아니면 하지 않는 것이 좋다. Object의 구현 되어 있는 equals 메서드가 잘 구현 되어 있어 비교 작업을 정확히 수행 해 준다.
재정의 할 때는 핵심 필드들을 모두 비교해야하며 다섯 가지 규약이 잘 지켜져 있는지 비교해야 한다.
'Book > Effective Java' 카테고리의 다른 글
[Item 14] Comparable을 구현할지 고려하라 (0) | 2022.07.19 |
---|---|
[ITEM 13] clone 재정의는 주의해서 진행해라 (0) | 2022.07.13 |
[ITEM 12] toString을 항상 재정의하라 (0) | 2022.07.13 |
[ITEM 11] equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2022.07.10 |
[Book] ITEM 9) try-finally 대신 try-with-resource 를 사용하라 (0) | 2022.03.19 |
[Book] ITEM 8) finalizer 와 cleaner는 피하라 (0) | 2022.03.07 |
[Book] ITEM 7) 더이상 쓰지 않는 객체 레퍼런스는 없애자 (0) | 2022.03.04 |
[Book] ITEM 6) 불필요한 객체는 만들지 말자 (0) | 2022.03.03 |