泛型与类型擦除
public class K_GenricTypes {
public static void method(List list) {
System.out.println("method");
}
}
编译上面的类:javac -encoding utf-8 .\K_GenricTypes.java
生成class后反编译:javap -verbose .\K_GenricTypes.class
public class K_GenricTypes {
public static void method(List<String> list) {
System.out.println("method");
}
}
同样编译上面的代码,然后反编译。
对比下这两个类method方法反编译后的代码
泛型方法method(List<String> list)与非泛型方法method(List list)对比:
1、code属性完全一样
2、泛型方法比非泛型方法多了一个Signature属性。
因为java语言的泛型采用的是擦除法实现的伪泛型,在字节码(Code属性)中,泛型信息(类型变量、参数化类型)编译之后都通通被擦除掉。因此,对于运行期的Java语言来说,List<String>、List<Integer>是同一个类。
为了弥补擦除的不足,新增了Signature属性。Signature属性的作用是存储一个方法在字节码层面的特征签名,这个属性保存的参数类型不是原生类型,而是包括了参数化类型的信息。
在运行期,也可以通过反射获取泛型的信息,示例如下:
public class K_GenricTypes {
public static void method(List<String> list) {
System.out.println("method");
}
}
class K_GenricTypesMain {
public static void main(String[] args) throws Exception{
Method method = K_GenricTypes.class.getMethod("method",List.class);
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
System.out.println("参数类型:"+type);
//参数类型:java.util.List<java.lang.String>
if(type instanceof ParameterizedType){
Type[] paramType = ((ParameterizedType) type).getActualTypeArguments();
for (Type t : paramType) {
System.out.println("泛型类型:"+t);
//泛型类型:class java.lang.String
}
}
}
}
}