Generic 메타데이터 활용하기
참조 : http://blog.springsource.com/main/2006/09/29/exploiting-generics-metadata/
윗글 재미있습니다. 자바에서 욕을 많이 먹고 있는 기능 중에 하나가 Generic인데 사실 그렇게 욕먹을 필요까진 없다고 봅니다. 타입 캐스팅을 줄여주는 것 만으로도 충분히 좋은 기능이고 컴파일 시점에 타입 체크를 할 수 있다는 것도 좋다고 생각합니다. 단지 복잡해 보일 수도 있고 가독성을 떨어트릴 수도 있다는 것 때문에 사장되어야 할 정도로 엉망진창인 기능은 아니라고 생각합니다.
어쨋든 자바의 Generic은 자바 1.4 이하 버전들과의 호환 때문에 erasure 방식을 사용하고 따라서 런타임 시에 어떤 타입을 가지고 있는지 알겨를이 없습니다.
그런데 바로 이 Erasure 방식 때문에 오해가 생기기도 하나봅니다. 즉, 자바의 Generic은 타입 정보를 지워버린다는 오해입니다. 클래스 파일에 붙어있는 타입 정보는 지워지지 않습니다. 코딩을 해놨는데 그걸 굳이 지워버릴 필요는 없겠죠. 단지 런타임 시에 해당 클래스 타입의 객체에서 지워져버릴 뿐이죠. 따라서 클래스 파일에 붙어있는 타입 정보를 얼마든지 활용할 수도 있습니다.
Type[] genericInterfaces = calculatorType.getGenericInterfaces();
// find the generic interface declaration for EntitlementCalculator<E>
ParameterizedType genericInterface = null;
for (Type t : genericInterfaces) {
if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType)t;
if (EntitlementCalculator.class.equals(pt.getRawType())) {
genericInterface = pt;
break;
}
}
}
if(genericInterface == null) {
throw new IllegalArgumentException("Type '" + calculatorType
+ "' does not implement EntitlementCalculator<E>.");
}
return (Class)genericInterface.getActualTypeArguments()[0];
}
위 코드는 메소드 파라미터로 넘어온 클래스가 가지고 있는 타입 정보를 반환해주는 메소드 입니다. 객체가 아니라 클래스를 받고 있기 때문에 가능한 일이죠.