이펙티브 자바 완벽 공략 1부

아이템 10. 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를 잘못 구현하면 생기는 문제

  1. HashMap / HashSet 동작 깨짐
  2. 중복 데이터 허용됨
  3. 캐시 미스 발생
  4. 디버깅 난이도 폭증

👉 특히 backend에서는 치명적


그래서 실무에서는 이렇게 한다

  • 대부분 IDE 생성 (IntelliJ)
  • 또는 Lombok 사용
@EqualsAndHashCode

👉 직접 구현은 거의 하지 않음


이 글의 핵심 요약

  • equals는 강력하지만 위험한 메서드다
  • 필요 없는 경우 절대 재정의하지 않는다
  • 필요하다면 반드시 규약을 지켜야 한다
  • hashCode와 항상 함께 고려해야 한다


© 2020. All rights reserved.

SIKSIK