개발서적/Effective Java

    [Effective Java] ordinal 메서드 대신 인스턴스 필드를 사용하라

    ordinal 메서드 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는 ordinal이라는 메서드를 제공한다. public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET; public int numberOfMusicians() { return ordinal() + 1; } } ordinal 메서드의 문제를 유지보수성에 있다. 상수 선언을 바꾸는 순간 numberOfMusicians가 오동작하며, 이미 사용중인 정수와 같이 값이 같은 상수는 추가할 수 없다. ordinal은 EnumSet과 EnumMap과 같이 열거 타입 기반의 범용 자료구조에 쓸 목적으로 설계되었으므로 이런 용도가 아니라면 이 메서..

    [Effective java] 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; 정수 열거 패턴에는 다음과 같은 문제가 있다. 1. 타입 안전을 보장할 방법이 없다. public class IntegerEnumeration { public static void makeSa..

    [Effective Java] 타입 안전 이종 컨테이너를 고려하라

    Set, Map와 같이 단일원소 컨테이너에 사용되는 제네릭에서 매개변수화되는 대상은 컨테이너 자신이다. 따라서 하나의 컨테이너에서 매개변수화할 수 있는 타입의 수가 제한된다. 하지만 더 유연한 수단이 필요할 때가 있다. 예를 들면 데이터베이스의 행은 임의 개수의 열을 가질 수 있는데, 모두 열을 타입 안전하게 이용하면 좋을 것이다. 이를 위해 컨테이너 대신 키를 매개변수화한 다음, 컨테이너에 값을 넣거나 뺄 때 매개변수화한 키를 함께 제공할 수 있다. 이러한 설계 방식을 타입 안전 이종 컨테이너 패턴이라고 한다. [타입 안전 이종 컨테이너 패턴] public class Favorites { public void putFavorite(Class type, T instance); public T getFav..

    [Effective Java] 제네릭과 가변인수를 함께 쓸 때는 신중하라.

    가변인수와 제네릭의 조합 가변인수(... 문법)와 제네릭은 조합해서 사용하지 않는 편이 좋다. 가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 하나 자동으로 만들어지기 때문에, 가변인수 매개변수에 제네릭이나 매개변수화 타입이 포함되면 알기 어려운 컴파일 경고가 발생한다. Possible heap pollution from parameterized vararg tpye List static void dangerous(List... stringLists) { List intList = List.of(42); Object[] objects = stringLists; objects[0] = intList; // 힙 오염 발생 String s = stringLists[0].get(0); // ClassCa..

    [Effective Java] 한정적 와일드카드를 사용해 API 유연성을 높이라

    매개변수화 타입 = 불공변 매개변수화 타입은 불공변이다. 즉, Type1과 Type2가 있을 때 List는 List의 하위 타입도 상위 타입도 아니다. 예를 들어, List은 List 하지만 때론 불공변 방식보다 유연한 방법이 필요할 수 있다. 와일드 카드를 사용하지 않은 메서드의 결함 public class Stack { public Stack(); public void push(E e); public E pop(); public boolean isEmpty(); } // 일련의 원소를 스택에 넣는 메서드 (생산자) public void pushAll(Iterable src) { for(E e : src) push(e); } // 소비자 public void popAll(Collection dst) {..