☕️ JAVA/Effective JAVA

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

1HOON 2021. 11. 2. 19:56

 

아이템 10 : equals는 일반 규약을 지켜 재정의하라


equals를 재정의해야하는 Case

객체의 식별성이 아니라 논리적 동치성을 비교해야하는 경우

 

String, Integer 와 같은 값 클래스

String a = "가나다";
String b = "abc";

assertTrue(a.equals(b));

위와 같이 String 같은 값 클래스는 equals 메서드에게 객체 자체가 동일한지 여부보다 값이 동일한지 여부를 기대할 것이다.

 

JPA 영속성 Entity 클래스 (case by case)

@Entity
@EqualsAndHashCode(of = {"id"})
public class User {
	@Id
    @GeneratedValue
    private Long id;
    
    private String name;
    
    private LocalDateTime lastLoginDate;
}

User 엔티티 클래스는 객체의 식별성보다는 사용자 아이디를 통한 논리적 동치성을 검사한다. 두 사용자가 같은지 비교할 때는 name과 lastLoginDate 필드까지 비교할 필요는 없기 때문이다. (마지막 로그인 일자가 다르다고 해서 다른 사용자는 아니니까)

 

그렇다면 case by case라고 적은 이유는 무엇일까?

만약 Set 인스턴스에 User 엔티티를 추가할 때, equals를 재정의하지 않는다면 같은 사용자가 여러번 추가될 수 있게된다.

반대로, 아이디가 부여되지 않은 User 엔티티를 Set에 담고자하는 경우에는 equals를 재정의한 경우 중복으로 간주해 중복 제거가 되어버린다.

때문에 나같은 경우에는 equals는 재정의하되, Set에 담아서 처리해야하는 케이스를 최대한 피하는편이다.

 

재정의하지 않는것이 최선인 Case

  • 각 인스턴스가 본질적으로 고유할 경우
  • 인스턴스의 논리적 동치성을 검사할 일이 없는 경우
  • 상위 클래스에서 재정의한 equals가 하위 클래스에서도 맞는 경우
  • 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없는 경우

 


 

equals 재정의 시 따라야하는 일반 규약

일반 규약은 Java API에 명시되어있으며, JDK 18 기준 여기에서 확인할 수 있다.

  • 반사성(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 메서드 구현 방법

  1. == 연산자를 사용해 입력이 자기 자신의 참조인지 확인한다.
  2. instanceof 연산자로 입력이 올바른 타입인지 확인한다.
  3. 입력을 올바른 타입으로 형변환한다.
  4. 입력 객체와 자기 자신의 대응되는 '핵심' 필드들이 모두 일치하는지 하나씩 검사한다.

 


 

Referrence


 

이펙티브 자바 3/E - 교보문고

프로그래밍인사이트 | 자바 6 출시 직후 출간된 『이펙티브 자바 2판』 이후로 자바는 커다란 변화를 겪었다. 그래서 졸트상에 빛나는 이 책도 자바 언어와 라이브러리의 최신 기능을 십분 활용

www.kyobobook.co.kr

 

Object (Java SE 18 & JDK 18 [build 2])

java.lang.Object public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: 1.0 See Also: Constructor Summary Constructors Method S

download.java.net

 

반응형