How to get Generic Metadata from a Class at Runtime

altuure
altuure
Aug 31, 2010 · 2 min read

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] expected
First 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]);
}
}

altuure

Continous Developer Blog

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store