[Effective Java 3/e] 아이템 33 - 타입 안전 이종 컨테이너를 고려하라
아이템 33 - 타입 안전 이종 컨테이너를 고려하라
이종 컨테이너 패턴
- 컨테이너 대신 키를 매개변수화한 다음, 컨테이너에 값을 넣거나 뺄 때 매개변수화한 키를 함께 제공
- 값의 타입이 키와 같음을 보장
타입 안전 이종 컨테이너 패턴
public class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<>();
public <T> putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), instance);
}
public <T> getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
public static void main(String[] args) {
Favorites f = new Favorites();
f.putFavorite(String.class, "Java");
f.putFavorite(Integer.class, 0xcafebabe);
f.putFavorite(Class.class, Favorites.class);
String favoriteString = f.getFavorite(String.class);
int favoriteInteger = f.getFavorite(Integer.class);
Class<?> favoriteClass = f.getFavorite(Class.class);
System.out.printf("%s %x %s%n", favoriteString, favoriteInteger, favoriteClass.getName());
}
}
// output : Java cafebabe Favorites
동적 형변환으로 런타임 타입 안전성 확보
public <T> putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), type.cast(instance));
}
asSubclass를 사용해 한정적 타입 토큰을 안전하게 형변환한다
static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
Class<?> annotationType = null; // 비한정적 타입 토큰
try {
annotationType = Class.forName(annotationTypeName);
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
return element.getAnnotation(annotationType.asSubclass(Annotation.class));
}
- 컴파일 시점에는 타입을 알 수 없는 에너테이션을 asSubclass 메서드를 사용해 런타임에 읽어내는 방법