为什么 Java 的 Collection.toArray() 返回 Object[] 而不是 E[]?

发布于 2024-11-10 10:20:20 字数 794 浏览 9 评论 0原文

在 Java 泛型出现之前,Collection.toArray() 无法知道开发人员需要哪种类型的数组(特别是对于空集合)。据我了解,这是习语 collection.toArray(new E[0]) 背后的主要原理。

对于泛型,Collection.toArray() 只能返回一个充满 E 实例和/或其特化的数组。我想知道为什么返回类型仍然是 Object[] 而不是 E[] 。在我看来,返回 E[] 而不是 Object[] 不应破坏现有代码。

请参阅:集合.toArray(), 集合.toArray(T[]) 和相关主题 java: (String[])List.toArray() 给出 ClassCastException

Before Java generics, Collection.toArray() had no way to know which type of array the developer expected (particularly for an empty collection). As I understand it, this was the main rationale behind the idiom collection.toArray(new E[0]).

With generics, Collection<E>.toArray() can only return an array full of instances of E and/or its specialisations. I wonder why the return type still is as Object[] rather than E[]. In my opinion, returning an E[] instead of Object[] should not break existing code.

See: Collection.toArray(), Collection.toArray(T[]) and the related topic java: (String[])List.toArray() gives ClassCastException

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再可℃爱ぅ一点好了 2024-11-17 10:20:20

这是一个非常好的问题。答案是仿制药也称为“擦除”。它不仅仅是一个名字。泛型编码的信息仅在编译时使用,然后被删除。因此,JVM 甚至不知道这个泛型类型 E,因此它无法创建数组 E[]

其他方法 toArray(T[] a) 在运行时从参数接收有关类型的信息。这就是该方法的原型为 的原因。 T[] toArray(T[] a):它获取类型为T的数组,并且可以返回类型为T的数组。类型作为参数传递。

It is a very good question. The answer is that generics are also called "erasures." It is not just a name. The information coded by generics is used at compile time only and then is removed. So, JVM even does not know this generic type E, so it cannot create array E[].

Other method toArray(T[] a) receives the information about the type from the argument at runtime. This is the reason this method's prototype is <T> T[] toArray(T[] a): it gets array of type T and can return array of type T. The type is passed as a parameter.

山川志 2024-11-17 10:20:20

“类型擦除”只是部分解释:Collection 及其 toArray() 方法在运行时都没有任何有关 E 的信息。

也正是因为向后兼容,Collection.toArray() 仍必须返回 Object[]。在 Java 1.5 之前,无法知道集合的泛型类型,因此这是唯一合理的 API 设计。

"Type erasure" is only a partial explanation: Neither the Collection, nor its toArray() method have any information about E at run time.

It is also because of backwards compatibility, that Collection.toArray() must still return Object[]. Before Java 1.5, there was no way of knowing a generic type for a collection, so this was the only reasonable API design.

触ぅ动初心 2024-11-17 10:20:20

@Lukas,关于:“new E[]”

new E[0] 引发了编译器错误,正如您可能预期的那样。我找到的解决方法是:

Final E[] returnArray = (E[]) events.toArray( new Event[ events.size() ] );

注意,代码位于模板类 Listener 中。 E 扩展事件>。

在我的解决方法中,类型擦除既是问题也是解决方案。转换为 (E[]) 是安全的,因为它的精确类型被擦除为 Event[]。我看到的唯一缺点是编译器关于“未经检查或不安全操作”的警告(显然,在这种情况下,强制转换不是给定类型擦除的)。

@Lukas,关于向后兼容性,

我认为向后兼容性没有大问题。使返回类型更特殊与使参数类型更特殊不同。

换句话说,到目前为止期望 Collection.toArray() 返回 Object[] 的源代码应该非常高兴收到 E[]。

至于字节码,由于类型擦除,Object[] 和 E[] 无论如何都是相同的。

@Lukas, regarding: “new E[]”

The new E[0] raised the comiler error, as you probably expected. The workaround I have found is:

final E[] returnArray = (E[]) events.toArray( new Event[ events.size() ] );

N.B. the code is in a template class Listener<E extends Event>.

In my workaround, type erasure is both the problem and the solution. The cast to (E[]) is safe because its precise type is erased to Event[]. The only downside I see is the compiler warning about “unchecked or unsafe operations” (which, obviously, the cast is not in this case given type erasure).

@Lukas, regarding backward compatibility

I do not see a big problem with backward compatibility. Making the return type more special is not the same as making the argument type more special.

In other words, source code which so far expected Collection.toArray() to return an Object[] should be perfectly happy to receive an E[] instead.

And as to byte code, the Object[] and E[] are anyway the same due to type erasure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文