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

标签 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。)

最佳答案

您通过将原始 Object 添加到集合中而污染了堆(您必须进行强制转换才能实现)。这在技术上并不违法,但它是一个错误。

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

关于java - JLS 6/7 的哪些更改导致以下带有集合和泛型的未经检查的代码在 Java 7 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18486018/

相关文章:

java - 为什么某些 Java 包装类的名称与其原始类型不同?

c# - 使用字段指定泛型类型

java - 使用 eclipse 编译代码但不使用 javac

Java - 从类型 A 的类对象获取类型 A 数组的类对象?

c# - 这是使用泛型方法的好方法吗?

android - 如何解决 Android 工具中的 javac 增量构建未检测到应导致重新编译的更改?

compiler-construction - 破解 Open JDK - 发出 LLVM 汇编程序而不是 Java 字节码

java - 我的主要方法有什么问题?

java - 使用 copyToRealmOrUpdate 方法未在 Android 中更新 Realm 数据

java - 读写分离是否提高了程序效率?