类型擦除
一、初步了解
先看一下下面的这个例子:
public static void main(String[] args){
List<String> strList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(strList.getClass() == intList.getClass());
}
咱们可以先想一下,按照上面的例子最后输出的结果是什么?
首先想问一下,看到上面的例子会不会有说为啥不用equal来判断相等的?
这里判断 strList.getClass() 和 intList.getClass()
是否相等用的是 ==
而不是equals
,这个问题,其实用这两个都是一样的。使用equals的话,因为比较的都是.getClass()
最后还是在调 ==
来判断
继续说类型擦除的事;
前面的比较输出结果是:true
这就是因为java类型擦除造成的结果,在上面的strList.getClass() == intList.getClass()
比较中,已经不是List<String> 和 List<Integer>
的比较了,而是List和List
的比较。
因为java在运行编译生成的 .class
文件中是不包含泛型的类型信息的,虽然我们在使用泛型的时候加上了泛型的类型,但是在编译器编译的时候还是会把他去掉。
那么这个过程,就是我们所说的类型擦除,简单说就是在使用的时候加上的类型会在编译的时候被去掉
所以对于JVM来说,List和List<>
因此,泛型也叫做 伪泛型
二、类型擦除的基本过程
类型擦除的过程首先是要先将原本的类型信息找到已给具体的类来将原本的类型替换下来,这个类一般都是 Object类,当有了具体的类型信息将原本的类型信息擦除之后,就需要将原本的类型声明去掉,也就是 把List 中的 去掉,这样就只剩下 List,这样的也就基本实现了将List 转为 List的目的了。
但是这样还不太够,来看一下下面的例子:
class testDemo implements Comparablle<String>{
public int comparaTo(String str){
return 0;
}
}
对于上面的例子中经过了类型擦除时候,class testDemo implements Comparablle<String>
变成了 class testDemo implements Comparablle
这样的话,就相当于没有实现Comparablle
接口声明的int comparaTo(Object)
方法,这样代码在编译的时候就会报错。
所以除了上面说的替换类型意外还要能动态的生成一些桥接方法来保证程序正常编译。