【问题标题】:Generics and Arrays泛型和数组
【发布时间】:2014-12-04 09:01:05
【问题描述】:

我有这个代码:

List<Integer>[] intLists = new List[]{Arrays.asList(1)};
List<? extends Number>[] numLists = intLists;
numLists[0] = Arrays.asList(1.01);
double d1 = (Double)numLists[0].get(0); // ok
double d2 = intLists[0].get(0); // why java.lang.ClassCastException ?
double d2 = (Double)(Number)intLists[0].get(0); // I can do this way, but the question is not how but why
// the reason is in compiler! it adds implicin cast! after compilation code looks
double d2 = (Integer)intLists[0].get(0);

最后一行抛出的执行:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer

为什么?

intLists 中的运行时元素的类型为 ArrayList,而不是 ArrayList&lt;Integer&gt;ArrayList 中的元素是 Double

为什么不直接从列表中返回一个项目?

运行时没有Integer,怎么会出现?

【问题讨论】:

  • intLists 包含Integers,除非您明确将其分配给double,否则您不能将其分配给。
  • @abkvandrd 在您的intLists 中。你能显示 ypur inLists 数据吗?
  • intLists - 是数组,它不包含整数!它包含 ArrayList ,其中包含 Double。
  • 见:link 没有整数!

标签: java arrays generics


【解决方案1】:

intLists 和 numLists 都指向同一个数组,此时包含一个List&lt;Double&gt;

但是,由于编译器认为intLists[0]List&lt;Integer&gt; 类型,所以当您从中检索对象时,它会向Integer 添加一个强制转换。

所以你的第五行相当于double d2 = (Integer)intLists[0].get(0); 这将失败,因为intLists[0].get(0) 实际上是一个 Double。

关键是要明白,在第三行之后 intList 和 numList 都是相同的,您的 Integer 1 列表消失了。

你能走到这一步的原因是第二行。在这里,您将List&lt;Double&gt;[] 分配给元素类型为List&lt;? extends Number&gt; 的数组。这不应该被允许。这是 java 类型系统中的一个已知错误,也是不鼓励使用数组的原因。 请参阅this article 了解更多信息。

如果你尝试对列表做同样的事情,你会发现你做不到。

    List<List<Integer>> intLists = Arrays.asList(Arrays.asList(1));
    List<List<? extends Number>> numLists = intLists; // compile fails here.
    numLists.set(0, Arrays.asList(0.01d));
    double d1 = (Double)numLists.get(0).get(0); // ok
    double d2 = intLists.get(0).get(0); // why java.lang.ClassCastException ?

【讨论】:

  • 我明白了!谢谢!原因在于编译器!它增加了隐式演员表!谢谢!
【解决方案2】:

错误是“Double cannot be cast to Integer” intLists 必须返回一个 Integer 并且它会尝试这样做。

在返回分配给 d2 之前,它会对 List 元素的内容执行隐式转换为 Integer。这会导致强制转换异常。

【讨论】:

  • intLists 必须返回 ArrayList,因为它是 ArrayList 对象的数组
【解决方案3】:

由于您使用整数创建 intLists,并将此列表分配给扩展 NUMber 的通用列表,因此将仅采用整数格式。

    // List of Integers
    List<Integer>[] intLists = new List[]{Arrays.asList(1)}; 

    //This List will only acceptst the List of Integers as you are assiging Integer List to a generic List.        
    List<? extends Number>[] numLists = intLists; //This list.

所以,这里的问题在于

    numLists[0] = Arrays.asList(1.01);// Here is the problem.

只将整数值添加到可行的列表中。

【讨论】:

    【解决方案4】:

    对不起,在我之前的回答中,我没有注意到你在那里表演的小技巧。

    我认为这里发生的情况是,在内部,编译器已经在堆栈上准备了一个类型为Integer 的引用,准备分配intLists[0].get(0) 的结果。它在内部准备将 Integer 自动拆箱为 int,然后根据 intLists 成员的预期类型提升为 double

    但在运行时,它会将Double 放入该位置,并且无法将其分配给隐藏的、要自动取消装箱的Integer

    当您使用(Double)(Number) 时,它将所需的操作解释为不是自动取消装箱,然后是升级,而是将Integer (兼容)分配给Number,然后是(可能,基于运行时类)NumberDouble 的兼容分配,然后是从 Doubledouble 的自动拆箱。

    【讨论】:

      【解决方案5】:
      double d2 = intLists[0].get(0);
      

      此语句试图将 Integer 对象转换为 Double,然后将 Double 对象自动拆箱为 double 基元。但是在 java 中,包装类不能转换为其他包装类。即 Integer 不能转换为 Double。

      你应该试试:

      int i2 = intLists[0].get(0);
      double d2 = i2;
      

      【讨论】:

        猜你喜欢
        • 2011-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 2023-03-25
        • 2013-11-30
        相关资源
        最近更新 更多