繁体   English   中英

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

[英]Why does Java ArrayList use per-element casting instead of per-array casting?

Java的ArrayList<T> (可能还有很多其他类)中发生的事情是内部Object[] array = new Object[n]; ,写入T对象。 每当从中读取一个元素时,一个强制转换return (T) array[i]; 已经完成了。 所以,每次阅读时都要施展。

我想知道为什么这样做。 对我来说,似乎他们只是做了不必要的演员表。 创建一个T[] array = (T[]) new Object[n];是不是更合乎逻辑,也更快一点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语言的设计者要求我们明确使用哪种组件类型的原因。

每当从中读取一个元素时,一个强制转换return (T) array[i]; 已经完成了。 所以,每次阅读时都要施展。

Generic是编译时检查。 在运行时,使用类型T extends代替。 在这种情况下, T隐式extends Object因此您在运行时所拥有的是有效的。

return (Object) array[i];

要么

return array[i];

创建一个不是更合乎逻辑,也更快一点

T[] array = (T[]) new Object[n]

并不是的。 在运行时再次成为

Object[] array = (Object[]) new Object[n];

要么

Object[] array = new Object[n];

你真正钓鱼的是

T[] array = new T[n];

除了这不编译,主要是因为T在运行时不知道。

你能做的是

private final Class<T> tClass; // must be passed in the constructor

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

只有这样,数组实际上才是预期的类型。 这可以使读取速度更快,但代价是写入。 主要的好处是快速检查失败,即你会阻止一个集合被破坏,而不是等到你发现它被破坏后抛出异常。

我认为更多的是代码风格而不是性能或类型安全(因为支持数组是私有的)

java 5 ArrayList实现方式与您对E[]数组的建议方式相同。 如果您查看源代码,您会看到它包含7个(E [])强制转换。 从java 6开始, ArrayList更改为使用Object[]数组,该数组仅导致3(E)个转换。

数组也是对象。 这里T[] array = (T[]) new Object[n]你只投射(T [])对象类型而不是数组中的元素。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM