[Effective Java] 타입 안전이 보장되는 혼성(heterogeneous) 컨테이너의 사용을 고려하자. |
-
제네릭은 Set 이나 Map 같은 컬렉션, ThreadLocal 이나 AtomicReference 같은 단일 요소(single-element) 저장 컨테이너에 가장 많이 사용된다.
이 컬렉션들은 컨테이너를 매개변수화 한 것이다.
컨테이너의 특성에 따라 사용 가능한 타입 매개변수의 갯수가 자연스럽게 제한된다.
-
타입 안전을 지키면서 더 큰 유연성을 갖기 위해서 ( 예를 들면 nosql 처럼 column 이 상황에 따라 다른 경우 )는
컨테이너 대신 키(key) 를 매개변수화 해주면 된다.
-
Class 클래스는 1.5부터 제네릭화되었다.
클래스 리터럴 타입은 Class 가 아니고 Class<T> 이다.
예) String.class 는 Class<String> 타입이고, Integer.class 는 Class<Integer> 타입이다.
-
Class 를 key 로 사용하면, 타입 안전이 보장되면서 혼성(heterogeneous)이다.
일반적인 Map 과 다르게 모든 키가 서로 다른 타입일 수 있고, 값고 서로 다른 타입일 수 있다.
public class Sth{
private Map<Class<?>, Object> mSth = ...;
public <T> void putSth( Class<T> type, T instance ){
...
}
public <T> T getSth( Class<T> type ){
return type.cast( mSth.get( type ) );
}
}
이런 녀석을 타입 안전 혼성 컨테이너(typesafe heterogeneous container) 라고 한다.
-
위의 혼성 컨테이너는 client 가 type 을 원천 타입의 형태로 사용하면 타입 안전을 쉽게 훼손시킬 수 있다.
따라서 다음과 같이 하는 것이 더 견고하다.
public <T> void putSth( Class<T> type, T instance ){
mSth.put( type, type.cast( instance ) );
}
checkedSet, checkedList, checkedMap 등이 이와 동일한 기법을 사용한다.
-
위의 혼성 컨테이너의 또 다른 단점은 비구체화 타입(non-reifiable type) 에 사용될 수 없다.
즉 String, String[] 은 저장할 수 있지만, LIst<String> 은 저장할 수 없다.
List<String>.class 가 없기 때문.
이는 수퍼 타입 토큰( super type token ) 기법을 사용할 수 있지만, 나름의 제약이 더 있다는 것..
-
컨테이너에 제네릭을 사용하면 컨테이너 당 사용 가능한 타입 매개변수의 숫자가 제한된다.
그러나 컨테이너 자체보다는 요소의 키에 타입 매개변수를 두면 그런 제약을 극복할 수 있다.
이 경우 서로 다른 타입의 요소가 저장될 수 있어 혼성 컨테이너라고 부른다.
타입 안전이 보장되는 혼성 컨테이너의 키로 Class 객체를 사용할 수 있다. 이런 방식으로 사용되는 Class 객체를 토큰이라고 하며, 독자적인 키 타입을 사용할 수도 있다.
데이터베이스 행을 나타내는 DatabaseRow 타입을 만들 수 있으며, 그것의 키로 Column<T> 제네릭 타입을 사용할 수 있다.
'프로그래밍 놀이터 > 디자인 패턴, 리펙토링' 카테고리의 다른 글
[Effective Java] 배열보다는 List 를 사용하자. (0) | 2016.11.28 |
---|---|
[Effective Java] 컴파일 경고 메세지가 없게 하자. (0) | 2016.11.24 |
[Effective Java] 새로 작성하는 코드에서는 원천(raw) 타입을 사용하지 말자. (0) | 2016.11.21 |
[Effective Java] static 맴버 클래스를 많이 사용하자. (0) | 2016.11.17 |
[Effective Java] 전략을 표현할 때 함수 객체를 사용하자. (0) | 2016.11.15 |
댓글