现在的csdn没法看了,转来转去的文章,讲的乱七八糟的
问题:
在ArrayList或者CopyOnWriteArrayList等源码中,以Collection为参数的构造方法中为什么会出现红框中的判断呢,难道c.toArray()返回的还不一定是Object类型的数组?
探究:
打开 c.toArray的源码,发现是接口,我们随便找一个实现类,就例如最常见的ArrayList吧
注意,这里的elementData是ArrayList的内部数组,它是Object[]类型的 这点要格外注意一下,经过Arrays.copyOf复制返回后,还是Object[] 类型的,因为CopyOf方法默认不改变类型。
那既然如此,源码里为什么还会说 c.toArray might (incorrectly) not return Object[] 呢?
因为这里是JDK的设计缺陷(bug号6260652,可以去官方看详细解释)
不是所有Collection的实现类的 toArray
方法都返回 Object[] 类型
例如这里第二个例子,Arrays.asList()
所返回的实现类的toArray()
方法返回的就不是真正的Object[]
(可以去看它的源码,它返回的是泛型类型,就是你指定的类型) 那这样会导致什么问题呢?
会导致无法插入Object类型. 这时候如果有
// 抛出异常 java.lang.ArrayStoreException: java.lang.Object
objects2[0] = new Object();
存不进去,看到了吧。
也就是说,我们不能光根据声明时的类型来填充数据。例如
Object[] shuzu = new Integer[3];
这个数组就存不进去 Object类型的数据,所以他不是个真正能放Object的数组。
而ArrayList源码中的elementData数组一定要是Object[]类型的,所以这里才需要判断一下,如果不是,则用Arrays.copy转换一下。
总结:
至此彻底搞懂了,看来JDK设计的时候想让Collection的实现类的toArray方法返回Object类型,但是后来不知道什么原因,也能返回其他运行时类型了,这就尴尬了。
看来JDK设计缺陷还不少呢,还有一个关于装箱和拆箱的,详见
https://blog.csdn.net/qq_37186947/article/details/90322218