JLS 6/7的哪些更改导致以下带有集合和泛型的未检查代码在Java 7中工作?

JLS 6/7的哪些更改导致以下带有集合和泛型的未检查代码在Java 7中工作?,java,generics,javac,jls,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

下面的代码

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);
}
而在使用
javac
java
7时,它运行无误

这是语言变化、修复错误还是隐藏功能


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

您将原始对象添加到集合中(您必须进行演员舞才能实现),这会污染堆。从技术上讲,这并不违法,但它是一个bug


当您从隐式迭代器中提取值时,Java 6编译器似乎立即进行强制转换,而Java 7编译器则没有。如果不需要转换为
可序列化
(因为保持变量只是
对象
),则不转换为
可序列化
更有效,但据我从JLS了解,此行为是未定义的。尝试在两个
.class
文件上运行
javap
,并查看
循环的
周围的代码(可能就在调用
迭代器.next()
之后)?扩展对象
不可序列化我假设Java7在您可以将
转换为什么方面更自由。如果您只是强制转换
(List)
,这将在两个版本上都起作用。为了清楚起见,您能对Java 6中引发异常的行进行注释吗?我假设它是(objectel:list)的
{
@Peter,嗯……上面的问题确实是用javac 6编译的,所以……无论如何,我想只有
列表
变量的实际类型才重要,而不是我是如何完成作业的?@Paul,marked,谢谢!谢谢你的解释。我知道我的问题听起来很傻,但我真的很理解正在发生的事情,知道如何获取和读取字节码,我甚至知道,我的示例中的任何此类代码都应该立即修复——所有这些都是离题的。希望您的解释能帮助其他人。我的问题是——为什么Sun/Oracle Java 6和7之间的行为发生了变化?这是我回答中的一条旁注。;-)显然规范没有指定隐式转换的点是必需的,在这种情况下,Java 7编译器可以通过新的静态分析逻辑观察到,您总是将从集合中拉出的引用视为普通的
对象
,因此它不会浪费执行无关转换的指令。
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.io.Serializable