JLS 6/7的哪些变化导致以下未经检查的代码集合和泛型在Java 7中工作?

时间:2013-08-28 10:58:56

标签: java generics javac jls

以下代码

import java.util.*;
import java.io.*;

@SuppressWarnings("unchecked")
List<Serializable> list = (List<Serializable>) (List<?>)
  Collections.singletonList(new Object());

for (Object el : list) { // -> ClassCastException
  System.out.println(el);
}

是正确的Java(即使代码是可疑的)。使用javacjava 6会抛出

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.io.Serializable

在使用javacjava 7时运行时没有错误。

是语言更改,修复错误还是隐藏功能?

(注意:使用Eclipse编译的代码在所有选中的Eclipse版本上运行时没有错误 - Helios到Kepler。)

1 个答案:

答案 0 :(得分:2)

你通过将原始Object添加到集合中来污染堆(你必须进行投射舞蹈才能实现)。这在技术上并不违法,但这是一个错误。

当您从隐式迭代器中提取值时,Java 6编译器似乎是立即转换,而Java 7编译器则不是。如果它不需要(因为保持变量只是Serializable)而不转换为Object更有效,但据我从JLS理解,这种行为是未定义的。尝试在两个javap文件上运行.class并查看for循环周围的代码(可能就在invokeinterface Iterator.next() {{1}}之后。< / p>