이펙티브 자바 완벽 공략 1부
아이템 10. equals는 일반 규약을 지켜 재정의하라
아이템 9. equals는 일반 규약을 지켜 재정의하라
- 아이템 9. equals는 일반 규약을 지켜 재정의하라
핵심 정리: equals는 “필요할 때만” 재정의하라
equals()는 잘못 재정의하면 버그 + 컬렉션 문제 + 디버깅 지옥으로 이어진다. 그래서 가장 중요한 원칙은 다음이다.
재정의가 필요 없는 상황이라면, 아예 재정의하지 않는 것이 최선이다.
equals를 재정의하지 않아도 되는 경우
다음 조건 중 하나라도 만족하면 equals()를 재정의할 필요가 없다.
1. 인스턴스가 본질적으로 고유한 경우
각 객체가 “그 자체로 의미”를 가진다면 논리적 비교 자체가 필요 없다.
예시:
- Thread
- Socket
- Database Connection
👉 이런 객체는 “같다”의 의미가 없음 👉 단순히 동일한 객체인지 (==)만 중요
2. 논리적 동치성을 비교할 필요가 없는 경우
논리적 동치성(logical equality)이란:
서로 다른 객체라도 “의미적으로 같은 상태”인지 비교하는 것
하지만 모든 객체가 이런 비교를 필요로 하진 않는다.
예시:
new Object().equals(new Object()) // false
👉 대부분의 객체는 “같을 이유 자체가 없다”
3. 상위 클래스에서 이미 equals를 잘 구현한 경우
예시:
- List
- Set
- Map
이런 컬렉션 클래스는 이미:
- 값 기반 비교
- 순서 기반 비교 (List)
를 올바르게 구현하고 있다.
👉 굳이 재정의하면 오히려 규약 깨질 위험 있음
4. 클래스 사용 범위가 제한적인 경우
- private 클래스
- package-private 클래스
- 내부적으로만 사용하는 클래스
👉 외부에서 equals를 사용할 일이 없다면 👉 구현 자체가 의미 없음
Object 클래스와 equals
모든 클래스는 Object를 상속한다.
즉, 기본적으로 아래 메서드를 물려받는다.
- equals()
- hashCode()
- toString()
- clone()
- finalize()
👉 이 중에서 가장 많이 재정의되는 것이 equals()
Object의 기본 equals는 무엇인가?
public boolean equals(Object obj) {
return (this == obj);
}
👉 즉,
기본 equals는 “주소 비교”다 (참조 동일성)
equals를 재정의하는 이유
그렇다면 언제 equals를 재정의해야 할까?
👉 핵심 기준은 하나다.
“논리적으로 같은 객체”를 동일하게 취급해야 할 때
예시: Value Object
class User {
String name;
}
new User("A") vs new User("A")
- 주소: 다름
- 의미: 같음
👉 이런 경우 equals를 재정의해야 한다
흔한 오해 정리
❌ “문자열은 equals 필요 없다”
→ 틀린 설명
- String은 이미 equals를 재정의해 둔 상태
- 그래서 값 비교가 가능
"abc".equals("abc") // true
👉 직접 안 만들 뿐이지, 이미 구현되어 있음
❌ “싱글톤이라 equals 필요 없다”
→ 맞는 설명
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
}
👉 애초에 객체가 하나
👉 equals 의미 없음
❌ enum은 equals 필요 없다
→ 맞음
- enum은 JVM에서 단일 인스턴스 보장
- == 비교가 더 빠르고 안전
Color.RED == Color.RED
실무 관점 핵심 정리
이 부분이 진짜 중요하다.
equals를 잘못 구현하면 생기는 문제
- HashMap / HashSet 동작 깨짐
- 중복 데이터 허용됨
- 캐시 미스 발생
- 디버깅 난이도 폭증
👉 특히 backend에서는 치명적
그래서 실무에서는 이렇게 한다
- 대부분 IDE 생성 (IntelliJ)
- 또는 Lombok 사용
@EqualsAndHashCode
👉 직접 구현은 거의 하지 않음
이 글의 핵심 요약
- equals는 강력하지만 위험한 메서드다
- 필요 없는 경우 절대 재정의하지 않는다
- 필요하다면 반드시 규약을 지켜야 한다
- hashCode와 항상 함께 고려해야 한다