When a generic type information is required at runtime, it has to be passed in:
public class GenericClass<T> {
private final Class<T> type;
public GenericClass(Class<T> type) {
this.type = type;
}
public Class<T> getMyType() {
return this.type;
}
}
|
e.g. The following parameter information is available:
- the field parameters of its generic declaration by using: field.getGenericType()
- the parameter declared in the return generic type by using: method.getGenericReturnType()
- the parameter declared against all the method parameters by using: method.getGenericParameterTypes
public class GenericReflection
{
public static class B {
private A<String,
Integer> a;
public A<String,
Integer> get(final List<String> ls, final List<Integer> li) {
a = new A<String,
Integer>(ls.get(0), li.get(0));
return a;
}
}
public static class A<U, V> {
private final U u;
private final V v;
public A(final U u, V v) {
this.u = u;
this.v = v;
}
@A1
public U getU() {
return u;
}
public V getV() {
return v;
}
}
public static class IndexedType {
public int getIndex() {
return index;
}
public Class<?>
getType() {
return type;
}
private final int index;
private final Class<?> type;
public IndexedType(final int index, final Class<?> type) {
this.index = index;
this.type = type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + index;
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IndexedType other = (IndexedType) obj;
if (index != other.index)
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
@Override
public String toString()
{
return "IndexedType
[index=" + index + ", type=" + type + "]";
}
}
@Test
public void test() throws
NoSuchMethodException, SecurityException, NoSuchFieldException {
System.out.println("===test===");
final B b = new B();
Map<IndexedType,
List<Class<?>>> parameterizedReturnTypeMap = getParameterizedReturnTypes(b, "get", List.class, List.class);
System.out.println("returnParameterTypes:" + parameterizedReturnTypeMap);
Map<IndexedType,
List<Class<?>>> parameterizedParameterTypeMap = getParameterizedParameterMap(b, "get", List.class,
List.class);
System.out.println("parameterParametersMap:" + parameterizedParameterTypeMap);
Map<IndexedType,
List<Class<?>>> parameterizedFieldArgumentTypeMap = getParameterizedFieldArgumentTypeMap(b, "a");
System.out.println("fieldArgTypeList:" + parameterizedFieldArgumentTypeMap);
}
public static
Map<IndexedType, List<Class<?>>>
getParameterizedReturnTypes(Object obj, String methodName, Class<?>...
parameterTypes)
throws
NoSuchMethodException, SecurityException {
final Method method = obj.getClass().getMethod(methodName, parameterTypes);
final Type genericReturnType = method.getGenericReturnType();
final Type[] genericTypes = new Type[]{genericReturnType};
final
Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes);
return parameterizedTypeMap;
}
public static
Map<IndexedType, List<Class<?>>>
getParameterizedParameterMap(Object obj, String methodName,
Class<?>... parameterTypes) throws
NoSuchMethodException, SecurityException {
Method method = obj.getClass().getMethod(methodName, parameterTypes);
Type[] genericTypes = method.getGenericParameterTypes();
final
Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes);
return parameterizedTypeMap;
}
public static
Map<IndexedType, List<Class<?>>>
getParameterizedFieldArgumentTypeMap(Object obj, String fieldName) throws NoSuchFieldException,
SecurityException {
final Field field = obj.getClass().getDeclaredField(fieldName);
final Type genericFieldType = field.getGenericType();
final Type[] genericTypes = new Type[]{genericFieldType};
final
Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes);
return parameterizedTypeMap;
}
private static
Map<IndexedType, List<Class<?>>>
getParameterizedTypeMap(Type[] genericTypes) {
final
Map<IndexedType, List<Class<?>>> parameterizedTypeMap = new HashMap<>();
int index = 0;
for (Type genericType : genericTypes) {
if (genericType instanceof ParameterizedType)
{
ParameterizedType aParameterizedType =
(ParameterizedType) genericType;
final
List<Class<?>> actualTypeArgumentClassList = new
ArrayList<>();
Class<?> aParameterizedTypeClass = (Class<?>)
aParameterizedType.getRawType();
parameterizedTypeMap.put(new IndexedType(index++, aParameterizedTypeClass), actualTypeArgumentClassList);
Type[] actualTypeArguments = aParameterizedType.getActualTypeArguments();
for (Type typeArgument : actualTypeArguments) {
Class<?>
actualTypeArgumentClass = (Class<?>)
typeArgument;
actualTypeArgumentClassList.add(actualTypeArgumentClass);
}
}
}
return parameterizedTypeMap;
}
@Test
public void
testTypeSafeCache() {
System.out.println("===testTypeSafeCache===");
final TypeSafeCache cache = new TypeSafeCache();
cache.put(Integer.class, 1);
cache.put(Long.class, 1L);
cache.put(Double.class, 1.0);
System.out.println(cache.get(Integer.class));
System.out.println(cache.get(Long.class));
System.out.println(cache.get(Double.class));
}
@Test
public void
testTypeSafeAnnotationType() throws NoSuchMethodException,
SecurityException {
System.out.println("===testTypeSafeAnnotationType===");
final A<String,
Integer> a = new A<>("A", 1);
Method method = a.getClass().getMethod("getU");
System.out.println("method" + method);
Annotation a1 = method.getAnnotation(A1.class);
System.out.println("annotationType:" + a1.annotationType());
System.out.println("annotationType().getCanonicalName():" + a1.annotationType().getCanonicalName());
System.out.println(
"annotationType().getClass().getCanonicalName():" + a1.annotationType().getClass().getCanonicalName());
System.out.println(".annotationType().getTypeName():" + a1.annotationType().getTypeName());
System.out.println(".annotationType().getGenericSuperclass():" + a1.annotationType().getGenericSuperclass());
Annotation result = getAnnotation(method, a1.annotationType().getTypeName());
System.out.println("result:" + result);
}
}
|
===testTypeSafeCache===
1
1
1.0
===test===
returnParameterTypes:{IndexedType
[index=0, type=class
com.americanexpress.ssae.sample.generic.GenericReflection$A]=[class
java.lang.String, class java.lang.Integer]}
parameterParametersMap:{IndexedType
[index=0, type=interface java.util.List]=[class java.lang.String], IndexedType
[index=1, type=interface java.util.List]=[class java.lang.Integer]}
===testTypeSafeAnnotationType===
method:public
java.lang.Object
com.americanexpress.ssae.sample.generic.GenericReflection$A.getU()
annotationType:interface
com.americanexpress.ssae.sample.generic.GenericReflection$A1
annotationType().getCanonicalName():com.americanexpress.ssae.sample.generic.GenericReflection.A1
annotationType().getClass().getCanonicalName():java.lang.Class
.annotationType().getTypeName():com.americanexpress.ssae.sample.generic.GenericReflection$A1
.annotationType().getGenericSuperclass():null
annotationType:interface
com.americanexpress.ssae.sample.generic.GenericReflection$A1
result:@com.americanexpress.ssae.sample.generic.GenericReflection$A1()
|