Item10. equals는 일반 규약을 지켜 재정의하라

연어는결국강으로·2022년 12월 20일
0

이펙티브자바

목록 보기
2/7
  • equals는 재정의하는게 쉽지 않다.

equals를 재정의 하지 않아도 되는 경우

  • 각 인스턴스가 본질적으로 고유하다.
  • 인스턴스의 ‘논리적 동치성’을 검사할 일이 없다.
    • 클라이언트가 논리적 동치성을 검사하는 방식이 필요하지 않다고 생각한다면
    • → Object의 기본 eqauls만으로 해결된다.
  • 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다.
  • 클래스가 private거나 package-private이고 eqauls 매서드를 호출할 일이 없다.
    // eqauls 호출을 막는 매서드
    @Overide
    public boolean eqauls(Object object) {
    	throw new AssertionError(); // 호출 금지
    }

eqauls를 재정의해야 할 때

  • 객체 식별성이 아니라 논리적 동치성을 확인해야 하는데,
  • 상위 클래스의 equals가 논리적 동치성을 비교하도록 재정의하지 않았을 때
  • 주로 값 클래스가 해당된다.
    • 같이 값이 같은 인스턴스가 둘 이상 만들어 지지 않는다면 재정의 x( Item1 정적 팩터리 매서드, Item34 Enum )

equals 일반 규약

  • 전제 : 변수 x, y, z는 null이 아닌 모든 참조값이다.
  • 반사성 : x에 대해 x.equals(x) = true 이다.
  • 대칭성 : x, y에 대해 ( x.equals(y) == true ) → ( y.equals(x) == true ) 이다.
  • 추이성 : x, y, z에 대해 ( x.equals(y) == true ) & ( y.equals(z) ==true ) → ( x.equals(z) == true )
  • 일관성 : x, y에 대해 x.equals(y)를 반복 호출하면 항상 true 나 false를 반환한다.
  • null - 아님 : x.equals.(null)은 항상 false이다.

Object 명세에서 말하는 동치관계

  • 집합을 서로 같은 원소들로 이뤄진 부분집합으로 나누는 연산
  • 반사성 : 객체가 자기 자신과 같아야 함.
  • 대칭성 : 서로에 대한 동치여부에 똑같이 답해야 함.
    • 예시

      	public final class CaseInsensiveString {
      		
      		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;
      		} 
    • 해당 클래스는 equals에서 대소문자를 무시한다.

    • String의 equals와 CaseInsensitiveString의 equals 는 다른 값을 반환한다.

    • 해당 클래스의 equals를 String과 연동시키겠다는 생각을 버려야한다.

    • 결과

      @Overide
      public boolean equals(Object o) {
      	return o instanceof CaseInsensitiveString &&
          	((CaseInsensitiveString) o).s.eqaulsIgnoreCase(s);
       }

0개의 댓글