我创建了列表
private final List<Double> 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,为什么不在ClassCastException
中抛出List<Double> listD = (List<Double>) listI;
?
因此,如果您尝试添加double num = listD.get(0);
,请抛出ClassCastException
答案 0 :(得分:2)
Java调用Arrays.asList
时推断的泛型类型参数是asList
- Integer
的参数的常见类型,因此新的ArrayList
是一个ArrayList<Integer>
,而不是ArrayList<Double>
。
Java不会在ClassCastException
抛出List<Double> listD = (List<Double>) listI;
,因为在运行时,类型擦除已经发生,而对于JVM,代码如下所示:
List listD = (List) listI;
这对JVM来说非常好。
ClassCastException
稍后出现,尝试将真正来自列表的Integer
转换为Double
。对于泛型,Java编译器将在检索项目时向泛型类型参数(在本例中为Double
)插入隐式强制转换。但是,它确实是Integer
。
在编译此代码时,应该在演员表上发出关于&#34;未经检查的演员&#34;的警告。将List<?>
投射到List<Double>
时。它警告你,你已经证明了这种可能性 - 以后可能ClassCastException
。
答案 1 :(得分:1)
为什么不在
List<Double> listD = (List<Double>) 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