为什么Java ArrayList使用每个元素的转换而不是每个数组的转换?

use*_*929 21 java casting arraylist

会发生什么Java的内部ArrayList<T>(也可能是许多其他类)是有一个内部Object[] array = new Object[n];,哪个T对象被写入.每当从中读取元素时,return (T) array[i];都会进行强制转换.所以,每次阅读时都要施展.

我想知道为什么这样做.对我来说,似乎他们只是做了不必要的演员表.是不是更合乎逻辑,也更快一点,只是创建一个T[] array = (T[]) new Object[n];然后只是return array[i];没有演员表?这只是每个数组创建一个强制转换,通常远远小于读取次数.

为什么他们的方法是首选的?我不明白为什么我的想法不是更严格?

mer*_*ike 18

它比这更复杂:泛型在字节代码中被擦除,而擦除则T[]Object[].同样,返回值get()变为Object.为了保持类型系统的完整性,在实际使用类时插入检查的强制转换,即

Integer i = list.get(0);
Run Code Online (Sandbox Code Playgroud)

将被删除

Integer i = (Integer) list.get(0);
Run Code Online (Sandbox Code Playgroud)

既然如此,ArrayList中的任何类型检查都是多余的.但它确实跑题了,因为两者(T)(T[])未经检查的铸件,并承担任何运行时开销.

可以编写一个检查过的ArrayList:

T[] array = Array.newInstance(tClass, n);
Run Code Online (Sandbox Code Playgroud)

这样可以防止堆污染,但代价是冗余类型检查(你无法抑制调用代码中的合成转换).它还需要调用者为ArrayList提供元素类型的类对象,这会使其api变得混乱并使其在通用代码中更难使用.

编辑:为什么禁止创建通用数组?

一个问题是检查数组,而未检查泛型.那是:

Object[] array = new String[1];
array[0] = 1; // throws ArrayStoreException

ArrayList list = new ArrayList<String>();
list.add(1); // causes heap pollution
Run Code Online (Sandbox Code Playgroud)

因此,阵列的组件类型很重要.我假设这就是Java语言的设计者要求我们明确使用哪种组件类型的原因.