본문 바로가기

개발/이펙티브 자바

Effective Java ( 이펙티브 자바 ) - 아이템 37 ordinal 인덱싱 대신 EnumMap을 사용하라 이따금 배열이나 리스트에서 원소를 꺼낼 때 ordinal 메서드로 인덱스를 얻는 코드가 있다. class Plant { enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL } final String name; final LifeCycle lifeCycle; Plant(String name, LifeCycle lifeCycle) { this.name = name; this.lifeCycle = lifeCycle; } @Override public String toString() { return name; } } 이제 정원에 심은 식물들을 배열 하나로 관리하고, 이들을 생애주기(한해살이, 여러해살이, 두해살이)별로 묶어보자. 생.. 더보기
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개)의 원소 타입을.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 29 이왕이면 제네릭 타입으로 만들라 제네릭 타입을 새로 만드는 일은 조금 더 어렵다. 그래도 배워두면 그만한 값어치는 충분히 한다. public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } poublic Object pop() { if (size == 0) throw new EmptyStackExc.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 28 배열보다는 리스트를 사용하라 배열과 제네릭 타입에는 중요한 차이가 두 가지 있다. 첫 번째, 배열은 공변(covariant)이다. 어려워 보이는 단어지만 뜻은 간단하다. Sub가 Super의 하위 타입이라면 배열 Sub[]는 배열 Super[]의 하위 타입이 된다(공변, 즉 함께 변한다는 뜻이다). 반면, 제네릭은 불공변이다. 즉, 서로 다른 타입 Type1과 Type2가 있을 때, List은 List의 하위 타입도 아니고, 상위 타입도 아니다. 이것만 보면 제네릭에 문제가 있다고 생각할 수도 있지만, 사실 문제가 있는 건 배열 쪽이다. 다음은 문법상 허용되는 코드다. Object[] objectArray = new Long[1]; objectArray[0] = "타입이 달라 넣을 수 없다."; // A.. 더보기