컨테이너 대신 키를 매개변수화한 다음, 컨테이너에 값을 넣거나 뺄 때 매개변수화한 키를 함께 제공
type token : 컴파일타임 타입 정보와 런타임 타입 정보를 알아내기 위해 메서드들이 주고 받는 class 리터럴
public class Favorites{
private Map<Class<?>, Object> favorites = new HashMap<>();
public <T> void putFavorite(Class<T> type, T instance){
favorites.put(Objects.requireNonNull(type), instance);
}
public <T> T getFavorite(Class<T> type){
return type.cast(favorites.get(type));
}
}
getFavorite
는 처음에 Map
에서 Class
를 꺼내면 Object 이기때문에 T 로 캐스팅하여 반환한다.
하지만 악의적인 클라이언트 코드를 통해 getFavorite 시 오류가 발생할 수 있다.
putFavorites(Class(Integer.class)), "Integer의 인스턴스가 아닙니다.");
int favoriteInteger = f.getFavorite(Integer.class);
ClassCastExcpetion
발생
이를 해결하기 위해 putFavorite 에 cast
메소드를 사용
public <T> void putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), type.cast(instance));
}
해당 코드로 변경시, getFavorite
메소드에서 오류가 발생하는 것이 아니라,
putFavorite
메소드에서 오류 발생
위의 Favotie 은 List 형태의 인스턴스를 저장을 할 수 가 없다.
List<String>.class
라는 Class 객체를 얻을 수 없기 때문이다.
하지만 슈퍼 타입 토큰을 통해 해당 부분을 우회하여 저장할 수 있다.
spring - ParameterizedTypeReference
Favorites f = new Favorites();
List<String> pets = Arrays.asList("개", "고양이", "앵무");
f.putFavotie(new TypeRef<List<String>>(){}. pets);
List<String> listOfStrings = f.getFavorite(new TypeRef<List<String>>(){});
ParameterizedTypeReference
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
ParameterizedTypeReference<List<String>> typeRef =
ParameterizedTypeReference<List<String>>() {};
ResponseEntity<List<String>> response = restTemplate.exchange("/fruit", HttpMethod.GET, null, typeRef);
List<String> fruits = response.getBody();