// 타입 안전 이종 컨테이너 패턴 (199-202쪽) publicclassFavorites { // 코드 33-3 타입 안전 이종 컨테이너 패턴 - 구현 (200쪽) private Map<Class<?>, Object> favorites = newHashMap<>();
public <T> voidputFavorite(Class<T> type, T instance) { favorites.put(Objects.requireNonNull(type), instance); }
public <T> T getFavorite(Class<T> type) { return type.cast(favorites.get(type)); } /* // 코드 33-4 동적 형변환으로 런타임 타입 안전성 확보 (202쪽) public <T> void putFavorite(Class<T> type, T instance) { favorites.put(Objects.requireNonNull(type), type.cast(instance)); } */
// 코드 33-2 타입 안전 이종 컨테이너 패턴 - 클라이언트 (199쪽) publicstaticvoidmain(String[] args) { Favoritesf=newFavorites();
Exception in thread "main" java.lang.ClassCastException: Cannot cast java.lang.String to java.lang.Integer at java.base/java.lang.Class.cast(Class.java:3606) at com.github.sejoung.codetest.generics.Favorites.getFavorite(Favorites.java:17) at com.github.sejoung.codetest.generics.Favorites.main(Favorites.java:36)
Process finished with exit code 1
위에 코드에서 f.putFavorite((Class)Integer.class, “나는 바보”); 처럼 로타입을 넘기면 컴파일은 정상인데 실행시에 ClassCastException이 발생한다.
하지만 일반 컬랙션에도 다음같은 문제가 있기 때문에 어느정도 감수한다면 타입안정성을 얻을수 있다.
Favorites 코드가 불변식을 어기는 일이 없도록 보장하려면 putFavorite를 수정하면된다.
// 타입 안전 이종 컨테이너 패턴 (199-202쪽) publicclassFavorites { // 코드 33-3 타입 안전 이종 컨테이너 패턴 - 구현 (200쪽) private Map<Class<?>, Object> favorites = newHashMap<>();
public <T> T getFavorite(Class<T> type) { return type.cast(favorites.get(type)); }
// 코드 33-4 동적 형변환으로 런타임 타입 안전성 확보 (202쪽) public <T> voidputFavorite(Class<T> type, T instance) { favorites.put(Objects.requireNonNull(type), type.cast(instance)); }
// 코드 33-2 타입 안전 이종 컨테이너 패턴 - 클라이언트 (199쪽) publicstaticvoidmain(String[] args) { Favoritesf=newFavorites();
publicclassFavorites { // 코드 33-3 타입 안전 이종 컨테이너 패턴 - 구현 (200쪽) private Map<TypeRef<?>, Object> favorites = newHashMap<>();
public <T> T getFavorite(TypeRef<T> tr) { if(tr.type instanceof Class<?>){ //일반클래스인 경우 return ((Class<T>)tr.type).cast(favorites.get(tr)); }else{ //제네릭타입인 경우 return ((Class<T>)((ParameterizedType)tr.type).getRawType()).cast(favorites.get(tr)); } }
// 코드 33-4 동적 형변환으로 런타임 타입 안전성 확보 (202쪽) public <T> voidputFavorite(TypeRef<T> tr, T instance) { favorites.put(Objects.requireNonNull(tr), instance); }
// 코드 33-2 타입 안전 이종 컨테이너 패턴 - 클라이언트 (199쪽) publicstaticvoidmain(String[] args) { Favoritesf=newFavorites(); f.putFavorite(newTypeRef<List<String>>(){}, Arrays.asList("바보","천재"));