【问题标题】:java: (String[])List.toArray() gives ClassCastExceptionjava: (String[])List.toArray() 给出 ClassCastException
【发布时间】:2011-08-07 02:46:38
【问题描述】:

以下代码(在 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();

当 v2 是 Object[0] 以及其中有字符串时也会发生这种情况。 知道为什么吗?

【问题讨论】:

  • 您可能想了解协变和逆变 -- en.wikipedia.org/wiki/…
  • 如果 T 是一个带有工厂方法进行实例化的接口的情况呢?
  • @LaceCard - 这只是与协变/逆变非常间接相关。真正的问题是,这是toArray() 方法的指定行为的直接结果。

标签: java list classcastexception toarray


【解决方案1】:

这是因为当你使用

 toArray() 

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

List 

而不是

List<String>

因为泛型只是源代码,在运行时不可用,因此无法确定要创建的数组类型。

使用

toArray(new String[v2.size()]);

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

【讨论】:

  • @Kaleb - 不正确。或者至少这不是最初的原因。 toArray 方法在集合类泛型之前就存在。
  • 这是正确的解决方案,但不是正确的解释。您不能将 Object[] 转换为 Double[],因为它是一种语言功能,仅此而已。它与泛型无关。您可以将 Object 转换为 Double 假设它确实是 Double。所以从逻辑上讲,你可以对数组做同样的事情,但它根本不是语言的一部分。如果您将 Object 转换为 Double,则会进行运行时检查以确保 Object 实际上是 Double。如果将 Double 转换为 Object,则不会进行运行时检查,因为 Object 位于 Double 的继承层次结构中。
  • 在 IntelliJ 中执行此操作时,我收到使用 toArray(new String[0]) 的警告:“在较旧的 Java 版本中,建议使用预大小数组作为反射调用,这是创建适当数组所必需的size 非常慢。但是,由于 OpenJDK 6 的更新较晚,此调用被内置,使得空数组版本的性能相同,有时甚至更好。此外,传递预先调整大小的数组对于并发集合也是危险的,因为两者之间可能存在竞争sizetoArray 通话。”
【解决方案2】:

你用错了toArray()

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

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

String[] v3 = v2.toArray(new String[v2.size()]);

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

【讨论】:

    【解决方案3】:
    String[] str = new String[list.size()];
    str = (String[]) list.toArray(str);
    

    这样使用。

    【讨论】:

    • 拜托!格式化你的代码!按“ctrl + k”全选,或在代码的第一个字母前加“`”,最后一个字母加“`”。写答案的时候也可以在顶部的帮助中选择“{}”!
    【解决方案4】:
    String[] v3 = v2.toArray(new String[0]); 
    

    也能做到这一点, 请注意,一旦为方法提供了正确的 ArrayType,您甚至不需要再进行强制转换。

    【讨论】:

      【解决方案5】:

      使用JDK 11 Stream API中的toArray,您可以通过这种方式解决更普遍的问题:

      Object[] v1 = new String[] {"a", "b", "c"}; // or array of another type
      String[] v2 = Arrays.stream(v1)
          .<String>map((Object v) -> v.toString()).toArray(String[]::new);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-10
        • 1970-01-01
        • 1970-01-01
        • 2016-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多