Java为何不支持泛型的数组的原因

泛型数组其实是挺严谨的,说白了就是在“编译的时候通过增加强制类型转换的代码,来避免用户编写出可能引发ClassCastException的代码”。这其实也算是Java引入泛型的一个目的。但是,一个颇具讽刺意味的问题出现了:如果允许了泛型数组,那么编译器添加的强制类型转换的代码就会有可能是错误的。


看下面的例子:

//下面的代码使用了泛型的数组,是无法通过编译的

GenTest<String> genArr[] = new GenTest<String>[2];

Object[] test = genArr;

GenTest<StringBuffer> strBuf = new GenTest<StringBuffer>();

strBuf.setValue(new StringBuffer());

test[0] = strBuf;

GenTest<String> ref = genArr[0]; //上面两行相当于使用数组移花接木,让Java编译器把GenTest<StringBuffer>当作了GenTest<String>

String value = ref.getValue();// 这里是重点!


上面的代码中,最后一行是重点。根据本文第一部分的介绍,“String value = ref.getValue()”会被替换成“String value =(String)ref.getValue()”。当然我们知道,ref实际上是指向一个存储着StringBuffer对象的GenTest对象。所以,编译器生成出来的代码是隐含着错误的,在运的时候就会抛出ClassCastException。

但是,如果没有“String value = ref.getValue();”这行代码,那么程序可以说没有任何错误。这全都是Java中多态的功劳。我们来分析一下,对于上面代码中创建出来的GenTest对象,其实无论value引用实际指向的是什么对象,对于类中的代码来说都是没有任何影响的——因为在GenTest类中,这个对象仅仅会被当作是基类型的对象(在这里也就是Object的对象)来使用。所以,无论是String的对象,还是StringBuffer的对象,都不可能引发任何问题。举例来说,如果调用valued的hashcode方法,那么,如果value指向的是String的对象,实际执行的就是String类中的hashcode方法,如果是StringBuffer的对象,那么实际执行的就是StringBuffer类中的hashcode方法。

从这里可以看出,即使支持泛型数组也不会带来什么灾难性的后果,最多就是可能引发ClassCastException。而且平心而论,这个还是程序员自己的错误,实在算不得是Java编译器的错误。但是从另一个角度看,这确实是个巨大的讽刺:泛型是为了消灭ClassCastException而出现的,但是在这个时候它自己却引发了ClassCastException。咱们中国人把这个叫做搬起石头砸自己的脚。

当然制定JSR的那帮子人可能没学过中文,但是他们肯定是发现了这个令他们纠结的问题。被标榜为Java 5重要feature的泛型竟然陷入了这么一个怪圈。于是,他们在某个月黑风高的晚上,在某个角落的会议室内,悄悄的决定一不做二不休——不支持泛型的数组了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,777评论 18 399
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 9,792评论 0 16
  • 集合框架: 1)特点:存储对象;长度可变;存储对象的类型可不同2)Collection(1)List:有序的;元素...
    Demo_Yang阅读 5,110评论 0 4
  • 11月5日,大咸宁举办了第一届马拉松,尽管有许多不如意之处,但把马拉松搬到了自家门口,省去了赴外地跑马车马劳...
    近在左右阅读 2,755评论 0 0
  • orz图咯OK咯饿了 孙哥咯哦揉你热死你
    小牛姑阅读 1,477评论 0 0

友情链接更多精彩内容