在写通用的dao的模块的时候, 需要获取具体子类的泛型类型:
比如:父类
public class Father<T, P, K> {
}
子类:
public class Son extends Father<String, Long, Integer>{
}
怎么获取到子类中, 这String, Long, Integer 的三个类型呢?
程序一:
public static void getPt() {
ParameterizedType type = (ParameterizedType)Son.class.getGenericSuperclass();
Type[] pts = type.getActualTypeArguments();
for(Type t : pts) {
System.out.println(t);
}
}
程序二:
在.class文件中 , Signature属性是可选的定长属性,位于ClassFile(§4.1),field_info(§4.5)或method_info(§4.6)结构的属性表中。在Java语言中,任何类、接口、初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数化类型(Parameterized Types),则Signature属性会为它记录泛型签名信息。
所以我们可以操作字节码来获取Signature属性,从而获取这些具体的类型, 常用的字节码工具有asm, javasist, 这里用javasist(需要导入其jar)
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.SignatureAttribute;
public class Test1 {
public static void main(String[] args) throws NotFoundException, BadBytecode {
ClassPool cp =new ClassPool(true);
CtClass ctClass = cp.get("jdk.clazz.Son");//类全路径
ClassFile classFile = ctClass.getClassFile();
SignatureAttribute attribute = (SignatureAttribute)classFile.getAttribute("Signature");
System.out.println(attribute.getSignature());
}
}
程序输出:Ljdk/clazz/Father<Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Integer;>;
比较:程序一 :简单, 不用导入其他包。 程序二: 需要字节码操作工具,但是更加强大。