java:(String [])List.toArray()给出了ClassCastException

Gav*_*iel 96 java list classcastexception toarray

以下代码(在android中运行)总是在第3行给出一个ClassCastException:

final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();
Run Code Online (Sandbox Code Playgroud)

它也发生在v2是Object [0]时,以及当它中有字符串时.任何想法为什么?

MeB*_*Guy 238

这是因为当你使用时

 toArray() 
Run Code Online (Sandbox Code Playgroud)

它返回一个Object [],它不能转换为String [](即使内容是字符串)这是因为toArray方法只得到一个

List 
Run Code Online (Sandbox Code Playgroud)

并不是

List<String>
Run Code Online (Sandbox Code Playgroud)

因为泛型是源代码唯一的东西,并且在运行时不可用,因此它无法确定要创建的数组类型.

使用

toArray(new String[v2.size()]);
Run Code Online (Sandbox Code Playgroud)

分配正确类型的数组(String []和正确的大小)

  • 这是正确的解决方案,但不是正确的解释.您不能将Object []强制转换为Double [],因为它是一种语言功能,仅此而已.它与Generics没有关系.您可以将Object强制转换为Double,假设它确实是Double.从逻辑上讲,你可以对数组做同样的事情,但它根本不是语言的一部分.如果将Object强制转换为Double,则会进行运行时检查以确保Object实际上是一个Double.如果将Double转换为Object,则不会进行运行时检查,因为Object位于Double的继承层次结构中. (9认同)
  • cuz泛型,这就是原因 (2认同)
  • @Kaleb - 不是真的.或者至少那不是最初的原因.在收集类是通用的之前,存在`toArray`方法. (2认同)
  • 在IntelliJ中执行此操作时,我收到一条警告,建议使用`toArray(new String [0])`,而不是:“在较早的Java版本中,建议使用预先设置大小的数组作为反射调用,这对于创建适当大小的数组是必需的速度很慢,但是由于OpenJDK 6的更新较晚,因此该调用很吸引人,使得空数组版本的性能相同,有时甚至更好。另外,传递预大小的数组对于并发收集是危险的,因为在“ size”和“ toArray”调用。” (2认同)

Dil*_*nga 35

你使用的是错的 toArray()

请记住,Java的泛型主要是语法糖.ArrayList实际上并不知道它的所有元素都是字符串.

要解决您的问题,请致电toArray(T[]).在你的情况下,

String[] v3 = v2.toArray(new String[v2.size()]);
Run Code Online (Sandbox Code Playgroud)

请注意,泛化形式toArray(T[])返回T[],因此不需要显式转换结果.