Ensuring Consistency
일관성 문제 해결하기
1. 일관성이란 무엇인가?
일관성은 두 객체가 같다면 (어느 하나 혹은 두 객체 모두가 수정되지 않는 한) 앞으로도 영원히 같아야 한다는 뜻입니다. 가변 객체는 비교 시점에 따라 서로 다를 수도 혹은 같을 수도 있는 반면, 불변 객체는 한 번 다르면 끝까지 다릅니다.
클래스를 작성할 때는 불변 클래스로 만드는 게 나을지를 심사숙고해야 합니다. 불변 클래스로 만들기로 했다면 equals가 한 번 같다고 한 객체가 어느 시점에나 영원히 같다고 답하고, 다르다고 한 객체에는 영원히 다르다고 답하도록 만들어야 합니다.
클래스가 불변이든 가변이든 equals의 판단에 신뢰할 수 없는 자원이 끼어들게 해서는 안 됩니다. 이 제약을 어기면 일반성 조건을 만족시키기가 아주 어렵습니다.
예컨대 java.net.URL
의 equals는 주어진 URL과 매핑된 호스트의 IP 주소를 이용해 비교합니다. 호스트 이름을 IP 주소로 바꾸려면 네트워크를 통해야 하는데, 그 결과가 항상 같다고 보장할 수 없습니다.
다음은 잘못된 equals 메서드의 예입니다:
이와 같이 null 검사는 필요하지 않습니다. equals의 대상이 null이라면 false를 반환하면 됩니다.
2. MyType 클래스 예제
equals가 타입을 확인하지 않으면 잘못된 타입의 인스턴스를 주었을 때 ClassCastException을 던져 일반 규약을 위배하게 됩니다. 그런데 instanceOf는 (두 번째 피연산자가 구분하지) 첫 번째 피연산자가 null이면 false를 반환합니다.
3. 핵심 필드 비교
입력 객체와 자기 자신의 '핵심' 필드들이 모두 일치하는지 확인합니다. 모든 필드가 일치하면 true를, 하나라도 다르면 false를 반환합니다.
이는 모든 필드가 일치하는지 비교하여 equals 메서드를 구현하는 예입니다.
4. 결론
== 연산자를 사용해 입력이 자기 자신의 참조인지 확인합니다.
instanceOf 연산자로 입력이 올바른 타입인지 확인합니다.
입력을 올바른 타입으로 형변환합니다.
입력 객체와 자기 자신의 대응되는 '핵심' 필드들이 모두 일치하는지 하나씩 검사합니다.
핵심 정리
꼭 필요한 경우가 아니라면 equals를 재정의하지 말자. 많은 경우에 Object의 equals가 원하는 비교를 정확히 수행해준다. 재정의해야 할 때는 그 클래스의 핵심 필드를 모두 빠짐없이, 다섯 가지 규약을 확실히 지켜가며 비교해야 한다.
Last updated