打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
看一看java泛型,在编译后是什么样的?

Java泛型(Generic) 的引入加强了参数类型的安全性,减少了类型的转换,它与C++中的模板(Temeplates) 比较类似,但是有一点不同的是:Java的泛型在编译器有效,在运行期被删除,也就是说所有的泛型参数类型在编译后会被清除掉,我们来看一个例子,代码如下:

程序很简单,编写了4个方法,arrayMethod方法接收String数组和Integer数组,这是一个典型的重载,listMethod接收元素类型为String和Integer的list变量。现在的问题是,这段程序是否能编译?如果不能?问题出在什么地方?

事实上,这段程序时无法编译的,编译时报错信息如下:

这段错误的意思:简单的的说就是方法签名重复,其实就是说listMethod(List intList)方法在编译时擦除类型后是listMethod(List intList)与另一个方法重复。这就是Java泛型擦除引起的问题:在编译后所有的泛型类型都会做相应的转化。转换规则如下:

  • List、List、List擦除后的类型为List

  • List[] 擦除后的类型为List[].

  • List 、List 擦除后的类型为List.

  • List擦除后的类型为List< serializable="">.

明白了这些规则,再看如下代码:

经过编译后的擦除处理,上面的代码和下面的程序时一致的:

Java编译后字节码中已经没有泛型的任何信息了,也就是说一个泛型类和一个普通类在经过编译后都指向了同一字节码,比如Foo类,经过编译后将只有一份Foo.class类,不管是Foo还是Foo引用的都是同一字节码。Java之所以如此处理,有两个原因:

  • 避免JVM的大换血。C++泛型生命期延续到了运行期,而Java是在编译期擦除掉的,我们想想,如果JVM也把泛型类型延续到运行期,那么JVM就需要进行大量的重构工作了。

  • 版本兼容:在编译期擦除可以更好的支持原生类型(Raw Type),在Java1.5或1.6...平台上,即使声明一个List这样的原生类型也是可以正常编译通过的,只是会产生警告信息而已。

明白了Java泛型是类型擦除的,我们就可以解释类似如下的问题了:

  1. 泛型的class对象是相同的:每个类都有一个class属性,泛型化不会改变class属性的返回值,例如:

以上代码返回true,原因很简单,List和List擦除后的类型都是List,没有任何区别。

2.泛型数组初始化时不能声明泛型,如下代码编译时通不过:

原因很简单,可以声明一个带有泛型参数的数组,但不能初始化该数组,因为执行了类型擦除操作,List[]与List[] 就是同一回事了,编译器拒绝如此声明。

3.instanceof不允许存在泛型参数

以下代码不能通过编译,原因一样,泛型类型被擦除了:

  

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
InfoQ: Java深度历险(五)——Java泛型
Java-TypeToken原理及泛型擦除
Java语法糖的味道:泛型与类型擦除
【深入Java虚拟机】之六:Java语法糖
Java泛型概念相关面试题汇总。
将集合转化为指定的数组
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服