Effect Java 제2판(Joshua Bloch / Addison Wesley) 을 공부하고 정리한 내용 입니다.

8. equals 메소드를 오버라이딩 할 때는 보편적 계약을 따르자.

다음 조건 중 어느 하나라도 만족하면 equals 오버라이드를 하지 않고 상속 받은 그대로 사용하자.

  • 클래스의 각 인스턴스가 본래부터 유일한 경우.
  • 두 인스턴스가 논리적으로 같은지 검사하지 않아도 되는 클래스의 경우
  • 수퍼 클래스에서 equals 메소드를 이미 오버라이딩 했고, 그 메소드를 그대로 사용해도 좋은 경우
  • private이나 패키지 전용(package-private) 클래스라서 이 클래스의 equals 메소드가 절대 호출되지 않아야 할 경우

 

객체 참조만으로 인스턴스의 동일 여부를 판단하는 것이 아니라, 인스턴스가 갖는 값을 비교하여 논리적으로 같은지 판단할 필요가 있는 클래스로써, 자신의 수퍼클래스에서 equals 메소드를 오버라이드 하지 않았을 때 Object.equals 를 오버라이드 하는 것이 좋다.

equals 메소드를 오버라이드 할 때는 이 메소드의 보편적 계약을 따라야 한다.
equals 메소드는 동등 관계(equivalence relation)을 구현하며, 그것은

  • 재귀적이다(Reflexive) : null이 아닌 모든 참조 값 x에 대해, x.equals(x)는 반드시 true를 반환해야 한다.
  • 대칭적이다(Symmetric) : null이 아닌 모든 참조 값 x와 y에 대해, y.equals(x)가 true를 반환한다면 x.equals(y)도 반드시 true를 반환해야 한다.
  • 이행적이다(Transitive) : null이 아닌 모든 참조 값 x, y, z에 대해, 만일 x.equals(y)가 true를 반환하고 y.equals(z)가 true를 반환한다면 x.equals(z)도 반드시 true를 반환해야 한다.
  • 일괄적이다(Consistent) : null이 아닌 모든 참조 값 x와 y에 대해, equals 메소드에서 객체 비교 시 사용하는 정보가 변경되지 않는다면, x.equals(y)를 여러 번 호출하더라도 일관성 있게 true 또는 false를 반환해야 한다.
  • null이 아닌 모든 참조 값 x에 대해, x.equals(null)은 반드시 false를 반환해야 한다.

 

좋은 equals 메소드를 만드는 방법은 다음과 같다.

  1. 객체의 값을 비교할 필요 없고 참조만으로 같은 객체인지 비교 가능하다면 == 연산자를 사용하자.
  2. instanceof 연산자를 사용해서 전달된 인자가 올바른 타입인지 확인하자.
  3. 인자 타입을 올바른 타입으로 변환한다.
  4. 클래스의 중요한(꼭 비교해야 하는) 필드 각각에 대해서는 인자로 전달된 객체의 필드와 현재 객체(equals) 메소드가 호출된)의 필드가 모두 같은지 빠뜨리지 말고 비교한다.
  5. 우리의 equals 메소드를 작성한 후에는 보편적 계약을 따르는지 확인하고 단위 테스트 코드를 작성하여 그런 속성들이 지켜지는지 검사한다.

 

유의 사항

  • equals 메소드를 오버라이드 할 때는 hashCode 메소드도 항상 오버라이드 한다.
  • 너무 똑똑한 척 하지마라. 단순히 필드 값이 같은지 검사하는 것이라면 equals 계약 준수가 어렵지 않다. 하지만 너무 지나치게 동일 여부를 비교하려 하면 문제가 생기기 쉽다.
  • equals 메소드의 인자 타입을 Object 대신 다른 타입으로 바꾸지 말자.

 

 

Posted by outliers
,