Java

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

quedevel 2022. 5. 24. 13:53
728x90
반응형
  • Object 명세에 적힌 규약 ❗

    1️⃣ 반사성 : null이 아닌 모든 참조 값 x에 대해, x.equals(x)는 true다.

    2️⃣ 대칭성 : null이 아닌 모든 참조 값 x,y에 대해, x.equals(y)가 true면 y.equals(x)도 true다.

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

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

    5️⃣ null-아님 : null이 아닌 모든 참조 값 x에 대해, x.equals(null)은 false다.


  • 잘못된 코드 - 대칭성 위배 ❗

    public final class CaseInsensitiveString {
      private final String s;
    
      public CaseInsensitiveString(String s){
          this.s = Object.requireNonNull(s);
      }
    
      // 대칭성 위배 !!
      @Override
      public boolean equals(Object o){
          if(o instanceof CaseInsensitiveString) return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
          if(o instanceof String) return s.equalsIgnoreCase(((String) o));
          return false;
      }
      ... 
    }
    ```<br>
    ⚠️`CaseInsensitiveString`의 `equals`는 일반`String`을 알고있지만 `String`의 `equals`는 `CaseInsensitiveString`의 존재를 모른다는데 있다.<br>
    ⚠️ `equals` 규약을 어기면 그 객체를 사용하는 다른 객체들이 어떻게 반응할지 알 수 없다.<br>
    ⚠️ 구체 클래스를 확장해 새로운 값을 추가하면서 `equals` 규약을 만족시킬 방법은 존재하지 않는다.<br><br><br>
  • 양질의 equals 메서드 구현 방법을 단계별로 정리 ❗

    1️⃣ == 연산자를 사용해 입력이 자기 자신의 참조인지 확인한다.

    2️⃣ instanceof 연산자로 입력이 올바른 타입인지 확인한다.

    3️⃣ 입력을 올바른 타입으로 형변환한다.

    4️⃣ 입력 객체와 자기 자신의 대응되는 '핵심'필드들이 모두 일치하는지 하나씩 검사한다.

참고 자료

Joshua Bloch, 『Effective Java 3/E』, 개앞맵시 옮김, 프로그래밍인사이트(2018)
http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788966262281&orderClick=LEa&Kc=

728x90
반응형