아이템 41 : 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스를 마커 인터페이스라 한다. 마커 애너테이션이 등장하면서 마커 인터페이스는 구식이 되었다는 이야기를 들어보았을 것이다. 하지만 사실이 아니다. 마커 인터페이스는 두 가지 면에서 마커 애너테이션보다 낫다. 첫 번째, 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다. 마커 인터페이스는 어엿한 타입이기 때문에, 마커 애너테이션을 사용했다면 런타임에야 발견될 오류를 컴파일타임에 잡을 수 있다. 두 번째, 적용 대상을 더 정밀하게 지정할 수 있다는 것이다. 반대로 마커 애너테이..
아이템 40 : @Override 애너테이션을 일관되게 사용하라 자바가 기본으로 제공하는 애너테이션 중 보통의 프로그래머에게 가장 중요한 것은 @Override일 것이다. @Override는 메서드 선언에만 달 수 있으며, 이 애너테이션이 달렸다는 것은 상위 타입의 메서드를 재정의했음을 뜻한다. 이 애너테이션을 일관되게 사용하면 여러 가지 악명 높은 버그들을 예방해준다. 상위 클래스의 메서드를 재정의하려는 모든 메서드에 @Override 애너테이션을 달자. 예외는 한 가지뿐이다. 구체 클래스에서 상위 클래스의 추상 메서드를 재정의할 때는 굳이 @Override를 달지 않아도 된다. 구체 클래스인데 아직 구현하지 않은 추상 메서드가 남아 있다면 컴파일러가 그 사실을 바로 알려주기 때문이다. @Overrid..
아이템 39 : 명명 패턴보다 애너테이션을 사용하라 전통적으로 도구나 프레임워크가 특별히 다뤄야 할 프로그램 요소에는 딱 구분되는 명명 패턴을 적용해왔다. 예컨데 테스트 프레임워크인 JUnit은 버전 3까지 테스트 메서드 이름을 test로 시작하게끔 했다. 효과적인 방법이지만 단점도 크다. 첫 번째, 오타가 나면 안 된다. 실수로 이름을 testSafetyOverride로 지으면 JUnit 3은 이 메서드를 무시하고 지나치기 때문에 개발자는 이 테스트가 통과했다고 오해할 수 있다. 두 번째, 올바른 프로그램 요소에서만 사용되리라 보증 할 방법이 없다는 것이다. 클래스 이름을 TestSafetyMechanisms로 지어 JUnit에 던져줬다고 해보자. 개발자는 이 클래스에 정의된 테스트 메서드들을 수행해주..
아이템 38 : 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라 열거 타입은 거의 모든 상황에서 타입 안전 열거 패턴보다 우수하다. 단, 예외가 하나 있으니, 타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 그럴 수 없다는 점이다. 달리 말하면, 타입 안전 열거 패턴은 열거한 값들을 그대로 가져온 다음 값을 더 추가하여 다른 목적으로 쓸 수 있는 반면, 열거 타입은 그렇게 할 수 없다는 뜻이다. 사실 대부분 상황에서 열거 타입을 확장하는 건 좋지 않은 생각이다. 확장한 타입의 원소는 기반 타입의 원소로 취급하지만 그 반대는 성립하지 않는다면 이상하지 않은가! 기반 타입과 확장된 타입들의 원소 모두를 순회할 방법도 마땅치 않다. 마지막으로, 확장성을 높이려면 고려할 요소가 늘어나 설계와 구..
아이템 37 : ordinal 인덱싱 대신 EnumMap을 사용하라 이따금 배열이나 리스트에서 원소를 꺼낼 때 ordinal 메서드로 인덱스를 얻는 코드가 있다. ordinal()을 배열 인덱스로 사용할 경우 동작은 하지만 문제가 발생할 것이다. 배열은 제네릭과 호환되지 않으니 비검사 형번환을 수행해야 하고 깔끔히 컴파일되지 않을 것이다. 이를 해결할 수 있는 방안이 있다. 여기서 배열은 실질적으로 열거 타입 상수를 값으로 매핑하는 일을 한다. 그러니 Map을 사용할 수 있다. 열거 타입을 키로 사용하도록 설계된 아주 빠른 Map 구현체가 존재한다. 바로 EnumMap이다. EnumMap을 사용하면 ordinal을 쓸때보다 짧고 명료하고 안전하다. 안전하지 않은 형변환은 쓰지 않고, 맵의 키인 열거 타입..
아이템 36 : 비트 필드 대신 EnumSet을 사용하라 열거한 값들이 주로 단독이 아닌 집합으로 사용될 경우, 예전에는 각 상수에 서로 다른 2의 거듭제곱 값을 할당한 정수 열거 패턴을 사용해 왔다. 1 2 3 4 5 6 7 8 9 public class Text { public static final int STYLE_BOLD = 1
아이템 35 : ordinal 메서드 대신 인스턴스 필드를 사용하라 대부분의 열거 타입 상수는 자연스럽게 하나의 정숫값에 대응된다. 그리고 모든 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는 ordinal이라는 메서드를 제공한다. 다음 코드는 합주단의 종류를 연주자가 1명인 솔로부터 10명인 디텍트까지 정의한 열거 타입이다. 1 2 3 4 5 6 public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() {return ordinal() + 1; } } Colored by Color Scripter 동작은 하지만 ..
아이템 34 : int 상수 대신 열거 타입을 사용하라 열거 타입은 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입이다. 정수 열거 패턴 기법에는 단점이 많다. 타입 안전을 보장할 방법이 없으며 표현력도 좋지않다. 오렌지를 건네야 할 메서드에 사과를 보내고 동등 연산자(==)로 비교하더라도 컴파일러는 아무런 경고 메시지를 출력하지 않는다. 정수 열거 패턴을 사용한 프로그램은 깨지기 쉽다. 평범한 상수를 나열한 것뿐이라 컴파일하면 그 값이 클라이언트 파일에 그대로 새겨진다. 따라서 상수의 값이 바뀌면 클라이언트도 반드시 다시 컴파일해야 한다. 다시 컴파일하지 않은 클라이언트는 실행이 되더라도 엉뚱하게 동작할 것이다. 정수 상수는 문자열로 출력하기가 다소 까다롭다. 그 값을 출력하거나..