当前位置: 首页 > 面试题库 >

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

颛孙晗昱
2023-03-14
问题内容

Java ArrayList<T>(可能还有许多其他类)内部发生的事情是有一个内部对象Object[] array = new Object[n];T对象被写入其中。每当从元素中读取元素时,return (T) array[i];都会进行转换。因此,每次读取时都要进行转换。

我不知道为什么要这样做。对我来说,似乎他们只是在做不必要的演员。只创建一个T[] array = (T[]) new Object[n];,然后不进行强制转换,是否更合乎逻辑,并且速度稍快一些return array[i];?每次阵列创建仅一次强制转换,通常
少于读取次数。

为什么首选他们的方法?我看不出为什么我的想法并不严格吗?


问题答案:

比这还复杂的多:泛型以字节码删除,而的擦除T[]Object[]。同样,的返回get()变为Object。为了保持类型系统的完整性,在实际使用该类时即插入一个选中的强制类型转换,即

Integer i = list.get(0);

将被删除到

Integer i = (Integer) list.get(0);

在这种情况下,ArrayList中的任何类型检查都是多余的。但这确实不重要,因为(T)(T[])都是 未经检查的
强制转换,并且不会产生运行时开销。

可以编写一个检查的ArrayList来执行以下操作:

T[] array = Array.newInstance(tClass, n);

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

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

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

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

ArrayList list = new ArrayList<String>();
list.add(1); // causes heap pollution

因此,数组的组件类型很重要。我认为这就是为什么Java语言的设计师要求我们明确使用哪种组件类型。



 类似资料: