How to get Generic Metadata from a Class at Runtime
Here you can see how to traverse the runtime information to get this information. You Can simply traverse the inheritance tree ofr the class and get the metadata of the generic definition. Somthing like
public static Type[] getGenericDefinitons(Class classFrom, Class class1) ;
Type[] types=getGenericDefinitons(MockClass1.class,GenericInterface.class);//[String.class,Long.class,Integer.class] expectedFirst The Sample Cases :public interface GenericInterface <T,K,L>{}public interface MockClass1 extends GenericInterface<String,Long,Integer>{}
public interface MockClass11<T,K,L> extends GenericInterface<T,K,L>{}
public interface MockClass12 extends MockClass11<String,Long,Integer>{}
public interface MockClass2 extends MockClass1{}public class MockClass3 implements GenericInterface<String,Long,Integer>{}
public class MockClass4 extends MockClass3{}public class GenericClass <T,K,L>{}
public class AMockClass2 extends AMockClass1{}
public class AMockClass1 extends GenericClass<String,Long,Integer>{}And the java class metadata traverser to retrieve the Generic Informationpublic class Utils {/**Get the Generic definition from a class for given class with given index
* @param clz Implementing class
* @param class1 class with generic definition
* @param index generic index
* @return null if not found
* */public static Type getGenericDefiniton( Class clz, Class class1, int index) {
Type[] t = getGenericDefinitons(clz, class1);
if (t != null && t.length > index)
return t[index];
return null;}
/**Get the Generic definitions from a class for given class
* @param clz Implementing class
* @param class1 class with generic definition
* @return null if not found
* */
public static Type[] getGenericDefinitons(Class clz, Class class1) {
Type[] t = null;
while (clz != null) {t = getGenericDefinitonsThis(clz, class1);
if (t != null)
return t;
Class[] interfaces = clz.getInterfaces();
for (Class class2 : interfaces) {
t = getGenericDefinitonsThis(class2, class1);
if (t != null)
return t;
}
clz = clz.getSuperclass();
}
return t;
}
/**Get the Generic definitions from a class for given class without looking super classes
* @param clz Implementing class
* @param class1 class with generic definition
* @return null if not found
* */
public static Type[] getGenericDefinitonsThis(Class classFrom, Class class1) {Type[] genericInterfaces = classFrom.getGenericInterfaces();
for (Type type : genericInterfaces) {
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;if (class1.isAssignableFrom((Class) pt.getRawType())) {
Type[] actualTypeArguments = pt.getActualTypeArguments();
return actualTypeArguments;
}
}}
// check if it if available on generic super class
Type genericSuperclass = classFrom.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericSuperclass;if (class1.equals(pt.getRawType())) {
Type[] actualTypeArguments = pt.getActualTypeArguments();
return actualTypeArguments;
}
}
return null;}}And the test casePS: This class is not tested for Multi-dimensional Generic Definitionspublic class UtilsTest {
@Test
public void simpleInterfaceExtend(){
Type[] genericDefinitons = Utils.getGenericDefinitons(MockClass1.class, GenericInterface.class);
compareResults(genericDefinitons);
}@Test
public void simpleInterfaceExtend2(){Type[] genericDefinitons = Utils.getGenericDefinitons(MockClass2.class, GenericInterface.class);
compareResults(genericDefinitons);
}
@Test
public void simpleInterfaceExtend3(){Type[] genericDefinitons = Utils.getGenericDefinitons(MockClass12.class, GenericInterface.class);
compareResults(genericDefinitons);
}
@Test
public void simpleInterfaceImplements(){
Type[] genericDefinitons = Utils.getGenericDefinitons(MockClass3.class, GenericInterface.class);
compareResults(genericDefinitons);
}
@Test
public void simpleInterfaceImplements2(){Type[] genericDefinitons = Utils.getGenericDefinitons(MockClass4.class, GenericInterface.class);
compareResults(genericDefinitons);
}@Test
public void simpleClassImplements(){
Type[] genericDefinitons = Utils.getGenericDefinitons(AMockClass1.class, GenericClass.class);
compareResults(genericDefinitons);
}
@Test
public void simpleClassImplements2(){Type[] genericDefinitons = Utils.getGenericDefinitons(AMockClass2.class, GenericClass.class);
compareResults(genericDefinitons);
}private void compareResults(Type[] genericDefinitons) {
assertEquals(String.class,genericDefinitons[0]);
assertEquals(Long.class,genericDefinitons[1]);
assertEquals(Integer.class,genericDefinitons[2]);
}}