小结:关于得到泛型的Class
总结:关于得到泛型的Class
获得类的泛型:
有一个类:
public class Test<T> { }
现在想获得T的Class。在JAVA目前的泛型机制下,不可能。(原因参见JAVA泛型机制。说白了就是泛型是在编译期获得的,而且有擦除机制。所以在编译前,JAVA也不知道T是啥,编译后,JAVA知道了然后忘记了。囧)
网上流传过一个方法,就是写下一个Test类的子类,然后在子类中调用类似
Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
这样的代码来获得T的Class 。 遗憾的是,这是个笑话,或者说没有满足我们的需求,因为要想用上面的代码,Test的子类必须这么写:
public class SonOfTest extends Test<String>{ }
否则会报类型转换异常:sun.reflect.generics.reflectiveObjects.TypeVariableImpl
仔细看上面的SonOfTest,你会发现 Test<String>这一段。就是说在继承的时候我们必须事先知道T的类型是String.
并且为String专门做一个子类。这样一来就利用多态机制绕过了这个问题。泛型的可能性少,这方法有用,如果很多的话,为每一个可能性都写个对应的子类那是坑爹呢。
所以我在这里遗憾的告诉大家,这是个死穴。
当然在这里我们还能用一个变通的方法解决我们的问题,就是不用泛型机制了,绕过去(当然这个方法也许不优美或者不一定适用)。
我们只要把Test类改造成下面这样:
public class Test<T> { private Class<T> clazz; //这就是我们想要得到的T的Class public Test(Class<T> clazz) { this.clazz = clazz; //T的Class就是这么得到的,囧 } }
是的,很简单,就是在Test构造的时候直接通过参数把T的Class告知就行。
使用的时候是这样的:
Test<String> test = new Test(String.class);
别打我。这是没办法的办法。话说回来,你既然在创建Test的时候,已经知道泛型的Class是个String,何苦不用简单的参数形式来获得,而非要用走不通的路去获得它呢?
获得方法参数的泛型:
想获得某个类的方法或者成员的泛型,就很简单,应为JAVA提供了方法,抛砖引玉:
String genericType = method.getGenericParameterTypes()[0].toString().split("<")[1].split(">")[0]; System.out.println(genericType);