为什么 List.toArray() 返回 Object[] 而不是 String[]?如何解决这个问题?
有谁知道为什么 Java 1.6 有这种行为:
List<String> list = ArrayList<String>();
String[] arr = (String[]) list.toArray();
我得到一个 ClassCastException,因为它返回 Object[] 而不是 String[]。
我以为 List
应该返回 T[] - 不?有谁知道为什么语言中存在这种不便? 以及如何解决这个问题?如何从 List
获取 String[] 而不循环遍历项目?
Does anybody know why Java 1.6 has this behaviour:
List<String> list = ArrayList<String>();
String[] arr = (String[]) list.toArray();
And I get a ClassCastException, because it returns Object[] and not String[].
I thoughtList<T>.toArray()
should return T[] - no? Does anyone have an answer why this inconvenience exists in the language?
And also how to work around this? How do I get a String[] from List<String>
without looping thru the items?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您需要传入一个数组,以便
toArray
可以将其运行时类型用作提示。尝试使用toArray(new String[0])
代替。您还可以传入预先确定大小的数组。要理解这一点,请考虑需要执行什么类型的擦除才能起作用
。如果 Java 允许这样做,那么它在擦除后所能做的最好的事情就是
大多数 toArray 实现都使用
java.lang.reflect.Array
在给定的情况下构造正确类型的输出数组类型提示作为类
。You need to pass in an array so its runtime type can be used as a hint by
toArray
. TrytoArray(new String[0])
instead. You can also pass in a pre-sized array.To understand, consider what type erasure would have to do to make
work. If Java allowed that, the best it could do post erasure is
Most
toArray
implementations usejava.lang.reflect.Array
to construct an output array of the right type given a type hint passed as aClass
.因为数组从一开始就存在于 Java 中,而泛型是在 Java 5 中才引入的。而
List.toArray()
方法是在 Java 1.2 中引入的,在泛型存在之前,所以它被指定为返回对象[]
。许多现有代码现在期望List.toArray()
返回Object[]
,因此现在无法更改。此外,泛型会在运行时被删除,因此 ArrayList 甚至无法根据需要构造正确类型的数组。
这个漏洞是
List.toArray(T[])
方法,它将返回一个正确类型的数组,前提是您给它一个正确类型的数组,以便它知道要使用什么类型。Because arrays have been in Java since the beginning, while generics were only introduced in Java 5. And the
List.toArray()
method was introduced in Java 1.2, before generics existed, and so it was specified to returnObject[]
. Lots of existing code now expectsList.toArray()
to returnObject[]
, so it can't be changed now.Furthermore, generics are erased at runtime, so
ArrayList
couldn't even construct an array of the proper type if it wanted to.The loophole for this is the
List.toArray(T[])
method, which will return you an array of the correct type, provided you give it an array of the correct type so it knows what type to use.要了解为什么会发生这种情况,只需查看
Collection.toArray()
然后查看 < code>Collection.toArray(T[] a) 方法。还要记住,Java 中的泛型会在运行时被删除。To understand why that happens, just have a look at the javadoc for
Collection.toArray()
and then look at theCollection.toArray(T[] a)
method. Also keep in mind that generics in Java are erased at runtime.从 Java 11 开始,它比
String[] str = list.toArray(new String[0])
或String[] str = list.toArray(new String[list.size()) 更容易])
:Since Java 11 it's even easier than
String[] str = list.toArray(new String[0])
orString[] str = list.toArray(new String[list.size()])
:原因有两个:
该方法先于泛型,他们无法在不破坏向后兼容性的情况下更改签名。
无论如何,由于
List
是在没有Class
的情况下构造的,因此实现无法构造T< 类型的数组/code>.
The reasons are two:
The method preceded Generics and they couldn't change the signature without breaking backwards compatibility.
In any case, as the
List
is constructed without aClass<T>
there is no way for the implementation to construct an array of typeT
.解决方法是使用:
这必然会引发:不兼容的类型:Object[]无法转换为String[]错误
Workaround will be to use:
This is bound to throw an : incompatible types: Object[] cannot be converted to String[] error