본문 바로가기

이펙티브자바

Effective Java ( 이펙티브 자바 ) - 아이템 41 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스를 마커 인터페이스라 한다. Serializable 인터페이스가 좋은 예다. Serializable은 자신을 구현한 클래스의 인스턴스는 ObjectOutputStream을 통해 쓸 수 있다고, 즉 직렬화 할 수 있다고 알려준다. 마커 애너테이션이 등장하면서 마커 인터페이스는 구식이 되었다는 이야기를 들어보았을 것이다. 하지만 사실이 아니다. 마커 인터페이스는 두 가지 면에서 마커 애너테이션보다 낫다. 첫 번째, 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다. 마커 인터페이스는 어엿한.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 39 명명 패턴보다 애너테이션 사용하라 전통적으로 도구나 프레임워크가 특별히 다뤄야 할 프로그램 요소에는 딱 구분되는 명명 패턴을 적용해왔다. 예컨대 테스트 프레임워크인 Junit은 버전 3까지 테스트 메서드 이름을 test로 시작하게끔 했다. 효과적인 방법이지만 단점도 크다. 첫 번째, 오타가 나면 안 된다. 실수로 이름을 tsetSafetyOverride로 지으면 Junit 3은 이 메서드를 무시하고 지나치기 때문에 개발자는 이 테스트가 통과했다고 오해할 수 있다. 두 번째, 올바른 프로그램 요소에서만 사용되리라 보증할 방법이 없다는 것이다. 예컨대 클래스 이름을 TestSafetyMechanisms로 지어 Junit에 던져줬다고 해보자. 개발자는 이 클래스에 정의된 테스트 메서드들을 수행해주길 기대하겠지.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 38 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라 열거 타입은 거의 모든 상황에서 이 책 초판에서 소개한 타입 안전 열거 패턴보다 우수하다. 단, 예외가 있으니 타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 그럴 수 없다는 점이다. 달리 말하면, 열거 타입은 값들을 그대로 가져온 다음 값을 추가하여 다른 목적으로 쓸 수 없다는 뜻이다. 실수로 이렇게 설계한 것은 아니다. 사실 대부분 상황에서 열거 타입을 확장하는건 좋지 않은 생각이다. 확장한 타입의 원소는 기반 타입의 원소로 취급하지만 그 반대는 성립하지 않는다면 이상하지 않은가! 확장성을 높이려면 고려할 요소가 늘어나 설계와 구현이 더욱 복잡해진다. 그런데 확장할 수 있는 열거 타입이 어울리는 쓰임이 최소한 하나는 있다. 바로 연산 코.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 36 비트 필드 대신 EnumSet을 사용하라 열거한 값들이 주로 (단독이 아닌) 집합으로 사용될 경우, 예전에는 각 상수에 서로 다른 2의 거듭제곱 값을 할당한 정수 열거 패턴을 사용해 왔다. public class Text { public static final int STYLE_BOLD = 1 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 35 ordinal 메서드 대신 인스턴스 필드를 사용하라 대부분의 열거 타입 상수는 자연스럽게 하나의 정숫값에 대응된다. 그리고 모든 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는 ordinal 이라는 메서드를 제공한다. 이런 이유로 열거 타입 상수와 연결된 정숫값이 필요하면 ordinal이라는 메서드를 제공한다. public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() { return ordinal() + 1; } } 동작은 하지만 유지보수하기가 끔찍한 코드다. 상수 선언 순서를 바꾸는 순간 numberOfMusi.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 34 int 상수 대신 열거 타입을 사용하라 열거 타입은 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입이다. 자바에서 열거 타입을 지원하기 전에는 정수 상수를 한 묶음 선언해서 사용하곤 했다. public static final int APPLE_FUJI= 0; public static final int APPLE_PIPPIN= 1; public static final int APPLE_GRANNY_SMITH= 2; public static final int ORANGE_NAVEL= 0; public static final int ORANGE_TEMPLE= 1; public static final int ORANGE_BLOOD= 2; 정수 열거 패턴(int enum pattern) 기.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 31 한정적 와일드카를 사용해 API 유연성을 높이라 매개변수화 타입은 불공변이다. 즉, 서로 다른 타입 Type1과 Type2가 있을 때 List은 List의 하위 타입도 상위 타입도 아니다. List은 List의 하위 타입이 아니라는 뜻인데, 곰곰이 따져보면 사실 이쪽이 말이 된다. List에는 어떤 객체든 넣은 수 있지만 List에는 문자열만 넣을 수 있다. 리스코프 치환 원칙에 어긋난다. 하지만 때론 불공변 방식보다 유연한 무언가가 필요하다. 여기 Stack의 public API를 추려보았다. public class Stack { public Stack(); public void push(E e); public E pop(); public boolean isEmpty(); } 여기에 일련의 원소를 스택.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 30 이왕이면 제네릭 메서드로 만들라 클래스와 마찬가지로, 메서드도 제네릭으로 만들 수 있다. 매개변수화 타입을 받는 정적 유틸리티 메서드는 보통 제네릭이다. 예컨대 Collections의 '알고리즘'메서드 ( sort, binarySearch 등 )는 모두 제네릭이다. public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll(s2); return result; } 컴파일은 되지만 경고가 두 개 발생한다. Set result = new HashSet(s1); result.addAll(s2); 경고를 없애려면 이 메서드를 타입 안전하게 만들어야 한다. 메서드 선언에서의 세 집합(입력 2개, 반환 1개)의 원소 타입을.. 더보기