【问题标题】:List<?> with Integers casted to List<Double>, why is that possible?将整数转换为 List<Double> 的 List<?>,为什么会这样?
【发布时间】:2014-06-10 07:35:01
【问题描述】:

我创建了列表
private final List&lt;Double&gt; prices
我有方法:

public Double getPrice(int i)
{
    i--;
    if (i >= this.prices.size())
    {
        return Double.NEGATIVE_INFINITY;
    }
    return this.prices.get(i);
}

而且看起来不错...但总是抛出:
ClassCastException: java.lang.Integer cannot be cast to java.lang.Double


经过一些测试,我发现:
我从配置创建此列表,但在配置中我使用不带点的数字,因此代码创建列表使用整数而不是双精度(ArrayList 内部包含整数)
但是为什么我可以将此列表转换为 List 而不会出现任何错误?
示例:

Integer a = 1;
Integer b = 1;
Integer c = 1;
Integer d = 1;
List<?> listI = new ArrayList<>(Arrays.asList(a, b, c, d));
List<Double> listD = (List<Double>) listI;
for (Object o : listD)
{
        System.out.println(o.getClass().getSimpleName()); // Integer
}
System.out.println("done");

这段代码没有任何错误,但是从 Double 列表中打印 Integer,为什么不在 List&lt;Double&gt; listD = (List&lt;Double&gt;) listI; 中抛出 ClassCastException
所以如果你尝试添加double num = listD.get(0); 然后抛出ClassCastException

【问题讨论】:

  • 您注意到警告了吗?

标签: java arraylist casting integer double


【解决方案1】:

为什么不在List&lt;Double&gt; listD = (List&lt;Double&gt;) listI; 中抛出 ClassCastException?

在运行时,所有类型信息都会丢失。您将原始类型与参数化类型混合在一起,这就是您在运行时遇到麻烦的原因。

试试这个

    List<Integer> listI = new ArrayList<Integer>(Arrays.asList(a, b, c, d));
    List<Double> listD = (List<Double>) listI; // compilation error
                                // Cannot cast from List<Integer> to List<Double>

示例代码:

    // Here's a basic parameterized list.
List<Integer> li = new ArrayList<Integer>();

    // It is legal to assign a parameterized type to a nonparameterized variable
List l = li;

    // This line is a bug, but it compiles and runs.
    // The Java 5.0 compiler will issue an unchecked warning about it.
    // If it appeared as part of a legacy class compiled with Java 1.4, however,
    // then we'd never even get the warning.
l.add("hello");

    // This line compiles without warning but throws ClassCastException at runtime.
    // Note that the failure can occur far away from the actual bug.
Integer i = li.get(0);

更多示例代码请查看Generic Types, Part 1 - O'Reilly Media

【讨论】:

  • @user2250333 我希望你现在明白了。
【解决方案2】:

Java 从Arrays.asList 的调用中推断出的泛型类型参数是asList 的参数的通用类型——Integer,所以新的ArrayListArrayList&lt;Integer&gt;,而不是@987654326 @。

Java 不会在 List&lt;Double&gt; listD = (List&lt;Double&gt;) listI; 处抛出 ClassCastException,因为在运行时,类型擦除已经发生,对于 JVM,代码如下所示:

List listD = (List) listI;

这对 JVM 来说非常好。

ClassCastException 稍后出现,来自尝试投射 Integer,这实际上来自将列表投射到 Double。使用泛型,Java 编译器将在检索项目时将隐式转换插入泛型类型参数,在本例中为Double。不过,确实是Integer

当您编译此代码时,应该有一个警告,关于将List&lt;?&gt; 转换为List&lt;Double&gt; 时的“未经检查的转换”。它会警告您所展示的可能性 - 稍后可能会出现ClassCastException

【讨论】:

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