![05a24b9f2364266de8aa8d3adc996a5b.png](https://i-blog.csdnimg.cn/blog_migrate/b8aefee8c4f151840eecab7b0bcc00c0.jpeg)
之前的文章,我们介绍了Java泛型的基本使用,这里我们将深入到编译期、虚拟机层面当中去。具体地,将会分析介绍类型擦除、泛型翻译方面的内容
类型擦除
在Java虚拟机JVM中是没有泛型这一说的,Java的泛型在编译期会被去除,即所谓的类型擦除。擦除后类型变量将由raw type原始类型来代替,具体地,如果泛型的类型变量上有类型限定,则第一个限定类型即为raw type,否则raw type为Object
/**
这里,我们对Pair类的Class文件反编译,由于Pair的类型变量T上没有类型限定,则类型擦除后该类型变量T将由Object代替,从下图红框我们也可以看到该类的first、second属性已经由T替换为Object了;而泛型方法minmax的类型变量T由于类型限定,故将使用第一个限定类型Comparable来作为raw type进行替换
![54c97849a41f592ae0e948b73f643c3f.png](https://i-blog.csdnimg.cn/blog_migrate/5d4806a6bc45c35faf6dc98621b8f285.jpeg)
泛型翻译
由于Java的类型擦除机制,使得泛型类在编译后可以认为就是一个普通的Java类,那如何保证类型正确呢?比如这里testPair1方法中getFirst、getSecond,由于类型擦除机制的存在,其应该返回的是Object类型,讲道理,不应该允许直接赋给String类型的变量啊
// 测试泛型类
其实,道理很简单,虽然字节码中的类型是Object了,但是编译器在调用这些方法的同时,会适当的自动的插入强制转换的指令,我们对该方法进行反编译,即可看到checkcast字节码指令
![f66e533b8a37c6e681144cd7011f8ca9.png](https://i-blog.csdnimg.cn/blog_migrate/7e58ae64cd8cd7f8884e8fcc824f6c2c.jpeg)
现在我们来介绍另外泛型翻译的情形——Bridge Method 桥方法。这里,提供了一个Pair的继承类
public
很明显,NumPair的setFirst方法是重写了父类的setFirst方法。但是由于类型擦除机制的存在,父类的setFirst方法的参数first其类型由T已经变为了Object,这一点从反编译后的结果也可以看出来。那么现在问题就来了,父类的方法签名是setFirst(Object first),而子类中该方法签名是setFirst(Integer first),二者不一样。目前看上去,类型擦除机制好像是与多态发生了冲突
![2e111a84cc784cd0385cdaf0707bb61c.png](https://i-blog.csdnimg.cn/blog_migrate/893587ee3b533e7e4982aa9842a0393e.jpeg)
我们先测试下,看看类型擦除机制与多态是否存在冲突
public
通过打印输出,我们可以确定子类的setFirst被正确地调用了,咦?多态与类型擦除机制二者之间好像又没有冲突了,而是父类与子类的setFirst方法之间签名确实不一样啊,这到底是怎么回事呢?
![40cf10646ac51dc3452685e17c30f4fb.png](https://i-blog.csdnimg.cn/blog_migrate/9c019386ec33f8ae67929659f41fd308.jpeg)
其实道理很简单,还是老办法,我们对子类的字节码文件进行反编译来一探究竟,从下图可以看出,编译器不仅生成我们所提供的setFirst(Integer first)方法,还帮我们自动生成了一个签名为setFirst(Object first)的新方法(如下图蓝框所示)。其实确实是由于类型擦除的原因,导致我们重写方法与父类方法在编译之后出现了签名不一致的情况。编译器为了解决这个冲突,使得多态特性不被破坏。其会自动生成一个与父类签名一致的方法setFirst(Object first),并在其内部去调用我们期望的setFirst(Integer first)方法。由于这个编译器自动生成的方法,一方面是负责来实际重写父类方法的,另一方面则是为了调用开发者实际提供的重写方法,故其被形象地称之为Bridge Method 桥方法
![f4722a8565768e7c560c4110238d0b26.png](https://i-blog.csdnimg.cn/blog_migrate/b8fc717d4399dab1a32a29879f9e780a.jpeg)
参考文献
- Java核心技术·卷I 凯.S.霍斯特曼著