타입 안전 이종 컨테이너 패턴
이다.public class Favorites{ // 추상화
public <T> void putFavorite(Class<T> type, T instance);
public <T> T getFavorite(Class<T> type)
}
- class의 리터럴 타입은 Class
다. - EX) String.class의 타입 Class
, Integer.class의 타입 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));
}
}
- 모든 키가 서로 다른 매개변수화 타입일 수 있다
- EX) 첫 번째는 Class
, 두 번째는 Class 일 수 있다.
public class Class<T>{
T cast(Object obj);
}
- cast 메서드는 형변환 연산자의 동적 버전이다. 단순히 주어진 인수가 Class 객체가 알려주는 타입의 인스턴스인지 확인 후 맞으면 그대로 반환 아니면 ClassCastException을 던진다.
- T 로 비검사 형변환하는 손실 없이도 Favorites 타입 안전하게 한다.
public <T> void putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), type.cast(instance));
}
- 제네릭과 로 타입을 섞어 사용하는 애플리케이션에서 클라이언트 코드가 컬렉션에 잘못된 타입의 원소를 넣지 못하게 추적하는 데 도움을 준다.
- List
과 List 는 같은 Class 객체를 공유한다. 모두를 허용하여 객체 참조를 한다면 오류가 많아질 것이다.
- 타입 토큰 : 컴파일 타임 타입 정보와 런타임 타입 정보를 알아내기 위해 주고 메서드들이 주고 받는 class 리터럴
public <T extends Annotation> T getAnnotation(Class<T> annotationType) // AnnotatedElement 인터페이스에 선언된 메소드
- 대상 요소에 달린 애너테이션을 런타임에 읽어오는 기능을 한다.
- 이 메소드는 리플렉션의 대상이 되는 타입(클래스, 메소드, 필드) 같은 프로그램 요소를 표현하는 타입에서 구현한다.
asSubClass
메소드 : 호출된 인스턴스 자신의 Class 객체를 인수가 명시한 클래스로 형변환한다.static Annotation getAnnotation(AnnotationElement 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))
}
Reference: