Java 泛型系列四:虚拟机是如何实现泛型的?
本文概述:
- 文章从底层实现原理上剖析了,泛型在 Java 中的实现;全文围绕泛型擦除展开,介绍了不同泛型编译前后的代码,并介绍了相关工具,同时补充了字节码细节,进一步说明了 Java 中的泛型,好像是伪泛型,哈哈哈;
虚拟机是如何实现泛型的:泛型擦除
-
概述:
- Java 虚拟机依托泛型擦除实现泛型,而C# 实现的是真真正正的泛型;
- JDK 其中实际上是伪泛型;
-
泛型擦除:编译后的效果
-
擦除效果:
-
原程序
public class A<T>{ private T data; } -
擦除后:
public class A<Object>{ private Object data; } -
复杂程序:指定了上界
public class A <T extends ArrayList & 接口B>{ private T data; public void test(){ data.接口B; } } -
擦除后:
//对于这种多实现的,编译期会将第一限制作为擦除后的类型,对于后面的,如果在某个方法中调用了后面的接口,那么编译器会在合适的位置插入强制转型的代码 public class A <ArrayList>{ private ArrayList data; //重点在强制转型 public void test(){ (接口B)data.接口B; } }
-
-
-
如何证明 JDK 中实际上是伪泛型:使用工具 jdui
-
工具展示:
-
源代码:
-
擦除后的效果:做了强制转型的
-
细节:有些泛型是看不到的
- 因为工具很强大,对于不同的代码的字节码呈现效果不同;
-
-
编程时的冲突问题:
-
冲突代码:
-
开发工具的局限性:IDEA 2019 + Java 8
-
代码展示:
-
编译结果展示:
-
-
JDK 判定方法是否重复:
- 方法返回值、方法名、参数;
-
开发工具判定方法是否重复:
- 方法名、参数;
-
-
JDK 内部对泛型做的优化:
-
在 Java 虚拟机中对泛型的字节码增加了许多属性:例如,signature
- 这个东西会记住原来的泛型类信息,
- 在 JDK 中是一个弱记忆,通过签名字段,在字节码中保留了相关信息;
-