이펙티브 자바 책을 읽으면서 새로 알게 된 부분을 기록한 것입니다.
Comparable을 구현할지 고려하라
- compareTo = Comparable 인터페이스의 유일한 메소드
- Object의 메소드가 아니다.
- 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제네릭하다.
- Comparable을 구현했다 == 그 클래스의 인스턴스들에는 자연적인 순서가 있음을 뜻함.
- Comparble을 구현한 객체들의 배열을 정렬하는 방법 ==
Arrays.sort(a)
- 자바 플랫폼 라이브러리의 모든 값 클래스와 열거 타입이 Comparable을 구현했다.
구현 방법
1
2
3
public interface Comparable<T> {
int compareTo(T t);
}
compareTo 메소드의 일반 규약
- 이 객체와 주어진 객체의 순서를 비교한다.
- 모든 객체에 대해 전역 동치관계를 부여하는 equals 메소드와 달리, compareTo는 타입이 다른 객체를 신경쓰지 않아도 된다. 타입이 다른 객체가 주어지면
ClassCastException
을 던진다. - 비교를 활용하는 클래스의 예
- 정렬된 컬렉션인 TreeSet과 TreeMap
- 검색과 정렬 알고리즘을 활용하는 유틸리티 클래스
- 두 객체의 참조 순서를 바꿔 비교하면 음양이 바뀐 결과가 나와야한다.
-> 첫 번째 객체가 두 번째보다 크고, 두 번째가 세 번째보다 크면 첫 번째는 반드시 세 번째보다 커야한다. - 크기가 같은 객체들끼리는 어떤 객체와 비교하더라도 항상 같아야 한다.
- compareTo 메소드로 수행한 동치성 테스트의 결과가 equals와 같아야 한다.
- 위 세 규약은 compareTo 메소드로 수행하는 동치성 검사도 equals 규약과 똑같이 반사성, 대칭성, 추이성을 충족해야함을 뜻함
- 기존 클래스를 확장한 구체 클래스에서 새로운 값 컴포넌트를 추가했다면 compareTo 규약을 지킬 방법이 없다.
- Comparable을 구현한 클래스를 확장해 값 컴포넌트를 추가하고 싶다면, 확장하는 대신 독립된 클래스를 만들고, 이 클래스에 원래 클래스의 인스턴스를 가리키는 필드를 두면 된다. 그 다음 내부 인스턴스를 반환하는 ‘뷰’ 메소드를 제공하면 된다. 이렇게 하면 바깥 클래스에 우리가 원하는 compareTo 메소드를 구현해 넣을 수 있다.
compareTo 메소드 작성 요령
- Compareble은 타입을 인수로 받는 제네릭 인터페이스이므로, compareTo 메소드의 인수 타입은 컴파일타임에 정해진다.
- 입력 인수의 타입을 확인하거나 형변환할 필요가 없다는 뜻
- 인수의 타입이 잘못됐다면 컴파일 자체가 되지 않음
- null을 인수로 넣어 호출하면 NullPointerException을 던져야 함