반응형

분류 전체보기 145

[Effective Java] Item38. 확장가능한 열거 타입이 필요하면 인터페이스

열거 타입과 확장 열거 타입은 거의 모든 상황에서 타입 안전 열거 패턴보다 우수하지만 확장하는 것은 좋지 않음 확장 타입의 원소는 기반 타입의 원소로 취급하지만 그 반대는 성립하지 않음 기반 타입과 확장 타입의 원소 모두 순회할 방법도 마땅치 않음 확장성을 높이려면 고려할 요소가 늘어남 확장 가능한 열거 타입 public interface Operation { double apply(double x, double y); } public enum BasicOperation implements Operation { PLUS("+") { public double apply(double x, double y) { return x + y; } }, MINUS("-") { public double apply(dou..

[Effective Java] Item 37. ordinal 인덱싱 대신 EnumMap

예제코드 public class Plant { enum LifeCycle { ANNUAL, PERNNIAL, BIENNIAL} final String name; final LifeCycle lifeCycle; public Plant(String name, LifeCycle lifeCycle) { this.name = name; this.lifeCycle = lifeCycle; } @Override public String toString() { return name; } } ordianl 인덱싱 Set[] plantsByLifeCycle = (Set[]) new Set[LifeCycle.values().length]; for (int i = 0 ; i < plantsByLifeCycle.length ; ..

[Effective Java] Item35. ordinal 대신 인스턴스 필드

public enum Role { CUSTOMER, SHOP_MANAGER; public int getAuth() { return ordinal(); } } 알바(PART_TIMER)를 추가 public enum Role { CUSTOMER, PART_TIMER, SHOP_MANAGER; public int getAuth() { return ordinal(); } } 문맥상 손님과 가게 사장 중간에 와야하므로 중간에 알바를 추가하면 순서가 달라지기 때문에 ordinal()메서드의 값이 달라짐 이 경우 ordinal()대신 인스턴스 필드에 값을 저장 public enum Role { CUSTOMER(0), SHOP_MANAGER(1); private final int auth; Role(int auth) ..

[Effective Java] Item34. int 대신 Enum

정수 열거 패턴(int enum pattern) - 사용 X 열거 타입이 생기기 전 공통적으로 사용되는 상수를 한데 묶어서 사용했었습니다. 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_NAVLE = 0; public static final int ORANGE_TEMPLE = 1; public static final int ORANGE_BLOOD = 2; 이런 식으로 사용한 것을 정수 열거 패턴(int enum pattern)이라고 합니다. 정수 열거 패턴의 단점 타..

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

제네릭은 Set, Map 등의 컬렉션과 TreadLocal 등의 단일원소 컨테이너에도 흔히 사용됩니다. 이런 모든 쓰임에서 매개변수화 되는 대상은 원소가 아닌 컨테이너 자신입니다. 따라서 하나의 컨테이너에서 매개변수화 할 수 있는 타입의 수가 제한됩니다. Set에는 단 하나의 타입 매개변수만 허용되며, Map에는 key와 value에 해당하는 두 개의 타입 매개변수만 허용됩니다. 이런 타입 매개변수의 갯수를 유연하게 하는 방법이 있습니다. 컨테이너 대신 키를 매개변수화한 다음 컨테이너에 값을 넣거나 뺄 때 매개변수화한 키를 함께 제공하는 것입니다. 이러한 설계 방식을 타입 안전 이종 컨테이너 패턴이라고 합니다. public class Favorites { private Map, Object>입니다. 이때..

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

가변인수(varargs) 메서드에 넘기는 인수의 개수를 클라이언트가 조절할 수 있게 해주는데, 컴파일시 배열로 처리 됩니다. 따라서 가변인수 매개변수에 제네릭이나 매개변수화 타입이 포함되면 아래와 같은 컴파일 경고가 발생합니다. public static void test(List... stringLists) { List intList = List.of(1); Object[] objects = stringLists; objects[0] = intList; // 힙 오염 String s = stringLists[0].get(0); // ClassCastException } 위 코드를 컴파일하면 아래와 같은 경고 메시지가 발생합니다. java: Test.java uses unchecked or unsafe o..

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

Item28에서 정리했던 것 처럼 매개변수화 타입은 불공변(invariant)입니다. 즉, List은 List의 하위타입이 아닙니다. 일반적으로는 이렇게 되는 것이 맞는 것 같습니다. 하지만 List에 Integer 타입을 추가하고 싶을 때가 있습니다. 매개변수화 타입은 불공변이기 때문에 불가능하지만 해결책은 있습니다. 한정적 와일드카드를 이용하는 것 입니다. 한정적 와일드 카드(Bounded Wildcards) Upper Bounded Wildcards: 타입제한을 풀어줄 때 사용, 제네릭 타입을 상위 제네릭 타입으로 묶을 때 사용 (List

[Effective Java] Item30. 이왕이면 제네릭 메서드로

클래스와 마찬가지로 메서드도 제네릭으로 만들 수 있습니다. 매개변수화 타입을 받는 정적 유틸 메서드는 보통 제네릭입니다. 제네릭 메서드 작성법은 제네릭 타입 작성법과 비슷합니다. public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll(s2); return result; } 컴파일은 정상적으로 되지만 2개의 경고 메시지가 발생합니다. 이 경고를 없애려면 메서드를 type-safe하게 만들어야 합니다. 타입 매개변수 명시 public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll(s2); return result; }..

[Effective Java] Item29. 이왕이면 제네릭 타입으로

클라이언트에서 직접 형변환해야 하는 타입보다 제네릭 타입이 더 안전하고 쓰기 편합니다. 이를 위해서는 제네릭 타입으로 만들어야 할 경우가 많습니다. 새로운 타입을 설계할 때 뿐만 아니라 기존 타입 중 제네릭이있어야 하는 게 있다면 제네릭 타입으로 변경하는 것이 좋습니다. 간단한 실습을 통해서 기존 코드를 제네릭 타입으로 바꾸는 것을 알아보겠습니다. 기존 코드 public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { this.elements = new Object[DEFAULT_INITIAL_CAPACITY];..