Set<E>
, Map<K,V>
등의 컬렉션과 ThreadLocal<T>
, AtomicReference<T>
등의 단일원소 컨테이너에도 흔히 쓰인다.Class<T>
다.String.class -> Class<String>
, Integer.class -> Class<Integer>
public class Favorites {
public <T> void putFavorite(Class<T> type, T instance) {
// ...
}
public <T> T getInstance(Class<T> type) {
return null; // 편의상 null을 리턴하도록 작성했다.
}
}
public class Favorites {
public static void main(String[] args) {
Favorites favorites = new Favorites();
favorites.putFavorite(String.class, "Java");
favorites.putFavorite(Integer.class, 0xcafebabe);
favorites.putFavorite(Class.class, Favorites.class);
String favoriteString = favorites.getInstance(String.class);
int favoriteInteger = favorites.getInstance(Integer.class);
Class<?> favoriteClass = favorites.getInstance(Class.class);
System.out.printf("%s %x %s%n", favoriteString, favoriteInteger, favoriteClass.getName());
}
}
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 getInstance(Class<T> type) {
return type.cast(favorites.get(type));
}
}
public class Class<T> {
T cast(Object obj);
}
public class Favorites {
public <T> void putFavorite(Class<T> type, T instance) {
favorites.put(Objects.requireNonNull(type), type.cast(instance));
}
}
첫 번째 제약 : Class 객체를 제네릭이 아닌 로 타입으로 넘지면 타입 안전성이 쉽게 깨질 수 있으므로 주의해야 한다.
두 번째 제약 : 실체화불가 타입에는 사용할 수 없다.
List<String>
은 저장할 수 없다.List<String>
을 저장하려는 코드는 컴파일되지 않는다. List<String>
용 Class 객체를 얻을 수 없기 때문이다.List<String>.class
라고 쓰면 문법 오류가 난다. List<String>.class
와 List<Integer>.class
를 이용해서 똑같은 타입의 객체 참조를 반환한다면 문제가 생길public interface AnnotatedElement {
// ...
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
// ...
}
java.lang.Class<T>
), 메서드(java.lang.reflect.Method
), 필드(java.lang.reflect.Fied
) 같이public class Item33 {
static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
Class<?> annotationType = null; // 비한정적 타입 토큰
try {
annotationType = Class.forName(annotationTypeName);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
return element.getAnnotation(annotationType.asSubclass(Annotation.class));
}
}
- ex. 데이터베이스의 행(컨테이너)를 표현한 DatabaseRow 타입
-> Column<T>