기억보다 기록을

[Effective JAVA] 이펙티브 자바 item10.equals는 일반 규약을 지켜 재정의하라 본문

Language/JAVA

[Effective JAVA] 이펙티브 자바 item10.equals는 일반 규약을 지켜 재정의하라

juyeong 2023. 1. 15. 22:55
반응형

 이펙티브 자바 스터디에서 아이템 10-12 파트를 발표하게 되었다. 해당 부분을 두번 읽었는데, 처음 읽을 때는 무슨소리지? 싶던 내용이 두번째 읽을 땐 '아, 이말이었구나.' 싶은 순간이 생기더라. 물론, 다른이에게 설명할 정도로는 부족하여 이 포스팅을 쓰며 차근차근 정리 후 내 것으로 만드는 시간이 필요하다 (이 책은 어색한 번역체와 불친절하게 느껴지는 예시들이 개선되면 더 좋은 평을 얻을 것 같다ㅎ) 해당 포스팅의 내용은 이펙티브 자바 책과 백기선 개발자의 강의, 그리고 구글링을 통해 구성되었다. 일부 사견을 포함한다. 

 

아이템 10은 '3장 모든 객체의 공통 메서드'의 첫 아이템이다. Object 클래스에서 final이 아닌 메서드 equals, hashcode, toString은 모두 재정의(overriding)를 염두에 두고 설계되었다. 이 오브젝트 메서드들을 언제, 어떻게 재정의 해야하는가? 

 

[Item 10] equals는 일반 규약을 지켜 재정의하라
- 자바에서 모든 클래스는 암묵적으로 object 클래스를 상속한다.
- 3장은 final이 아닌 메소드 "equals, hashcode, toString, clone, finalize"를 오버라이딩할 때 지켜야할 점에 대해 이야기한다.
- 그 중 equals는, "만들지 않아도 되면 굳이 만들지 않는 것이 좋다."
- 특히 아래 4가지 경우는 더욱 그렇다.
 
1) 각 인스턴스가 본질적으로 고유한 경우 (Singleton, Enum, Thread)
2) 인스턴스의 논리적 동치성 ('logical equality')를 검사할 일이 없는 경우 (String "Hello")
3) 상위 클래스에서 재정의한 equals가 하위 클래스에도 들어맞는 경우 (list, set: 부모클래스인 abstract list, abstract map에 잘 정의되어 있음)
4) 클래스가 private or package-private이고 equals 메서드를 호출할 일이 없는 경우 (밖에서 마음대로 참조할 수 없는 클래스인 경우 굳이 equals를 사용하지 않는다. 접근제한자가 public인 경우 누구나 참조해서 쓸 수 있기 때문에 어떻게 쓰일지 예측할 수 없다.)

equals 재정의 규약
1) 반사성 (A.equals(A) == true)
2) 대칭성 (A.equals(B) == B.equals(A))
3) 추이성 (A.equals(B) && B.equals(C), A.equals(C))
4) 일관성 (A.equals(B) == A.equals(B))
5) null이 아님 (A.equals(null) == false)

```
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} //반사성

if (!(o instanceof Point)){
return false;
} //instanceof로 타입비교

Point p = (point)o; //타입 형변환

return p.x == x && p.y == y; //핵심필드 같은지 비교
//double,float.compare(), nullable인 경우: objects.equals()
 
}
```

AutoValue 사용법
```
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<version>1.9</version>
</dependency>
```

```
@AutoValue
abstract class Point {
static Point create(int x, int y) {
return new AutoValue_Point(x, y);
}

abstract int x();
abstract int y();
}
```
lombok? @EqualsAndHashCode

 

반응형