본문 바로가기
책/이펙티브 자바 3판

[아이템 10] equals는 일반 규약을 지켜서 재정의하라.

by eunyoung 2023. 4. 20.

이펙티브 자바 3장 - 모든 객체의 공통 메서드

[아이템 10] equals는 일반 규약을 지켜서 재정의하라.


1. equals를 재정의 하지 않는 것이 좋은 상황

상황 1. 각 인스턴스가 본질적으로 고유하다.

 

값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스

대표적으로 Thread 클래스가 좋은 예이다.

 

상황 2. 인스턴스의 '논리적 동치성'을 검사할 일이 없다.

 

논리적 동치성을 검사하는 예 : java.util.regex.Pattern에서 두 Pattern의 인스턴스가 같은 정규 표현식을 나타내는지 검사

 

상황 3. 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다.

 

상황 4. 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없다.

 

 

2. equals를 재정의 하는 것이 좋은 상황

객체의 식별성(두 객체가 물리적으로 같은가) 판단 X

논리적 동치성 판단 O

 

객체의 식별성이 아니라 논리적 식별성을 판단해야 하는데, 상위 클래스의 equals가 논리적 동치성을 비교하도록 재정의되지 않은 상황

 

주로 값 클래스(Integer나 String처럼 값을 표현하는 클래스)들이 여기에 해당됨.

 

 

2-1 . 값 클래스에 equals를 재정의함으로써 얻을 수 있는 효과

 

그 인스턴스 값을 비교할 수 있게 되고, Map의 키와 Set의 원소로도 사용할 수 있음.

 

 

2-2. 값 클래스여도 equals를 재정의하지 않아도 되는 상황

 

값이 같은 인스턴스가 둘 이상 만들어지지 않음이 보장되는 인스턴스 통제 클래스라면 값 클래스여도 equals를 재정의하지 않아도 됨.

Enum이 여기에 해당됨. -> 논리적으로 같은 인스턴스가 2개 이상 만들어지지 않으니 논리적 동치성과 객체 식별성이 사실상 똑같은 의미임.

 

3. equals를 재정의할때 지켜야 하는 규약 - 동치 관계

 

3-1. 반사성

 

null인 아닌 모든 참조 값 x에 대해서, x.equals(x)는 true이다.

 

 

3-2. 대칭성

 

null이 아닌 모든 참조 값 x,y에 대해서 x.equals(y)가 true이면 y.equals(x)도 true이다.

 

 

3-3. 추이성

 

null이 아닌 모든 참조 값 x,y,z에 대해 x.equals(y)가 true이고 y.equals(z)도 true이면, x.equals(z)도 true이다.

 

 

3-4. 일관성

 

null이 아닌 모든 참조 값 x,y에 대해서 x.equals(y)를 반복해서 호출하면 항상 true를 반환하거나 항상 false를 반환한다.

 

 

3-5. null-아님

 

null이 아닌 모든 참조 값 x에 대해, x.equals(null)은 false이다.

 

 


[핵심정리]

꼭 필요한 경우가 아니라면 equals를 재정의하지 말자.

많은 경우에 Object의 equals가 원하는 비교를 정확히 수행해준다.

재정의할때는 그 클래스의 핵심 필드 모두를 빠짐없이, 다섯 가지 규약을 확실하게 지켜가며 비교해야 한다.