为什么要对 List< 进行泛型转换?将 Set..> 扩展为 List 在 Sun JDK 6 上成功,但在 Oracle JDK 7 上编译失败?

2024-03-21

下面的代码

class GenericCompilationFailureDemo {
    List<? extends GenericCompilationFailureDemo> newList() { 
        return new ArrayList<GenericCompilationFailureDemo>(); 
    };

    void useList() {
        List<GenericCompilationFailureDemo> list = 
            (List<GenericCompilationFailureDemo>) newList();
    }  

    List<? extends Set<GenericCompilationFailureDemo>> newListOfSpecificSets() { 
        return new ArrayList<Set<GenericCompilationFailureDemo>>(); 
    };

    void useListOfSpecificSets() {
        List<Set<GenericCompilationFailureDemo>> listOfSpecificSets = 
            (List<Set<GenericCompilationFailureDemo>>) newListOfSpecificSets();
    } 

    List<? extends Set<? extends GenericCompilationFailureDemo>> newListOfSets() { 
        return new ArrayList<Set<? extends GenericCompilationFailureDemo>>(); 
    };

    void useListOfSet() {
        List<Set<? extends GenericCompilationFailureDemo>> listOfSets = 
            (List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets();
    }  
}

在 Sun JDK 1.6.0_20(Windows Vista 上为 64 位,但我认为这没有任何区别)下编译,但在 Oracle JDK 1.7.0_01(同一平台)下导致以下编译失败:

[ERROR] src\main\java\GenericCompilationFailureDemo.java:[56,78] error: inconvertible types

请注意,第一个two“扩展至特定类型”强制转换useList and useListOfSpecificSets两者在 1.7.0_01 下仍然成功,所以这似乎与“双通用扩展”有关。

您知道 6 到 7 之间可能发生什么变化吗?观察到的行为是符合规范还是错误?

编辑回应 Sanjay 的评论:

@Sanjay:啊哈,有趣!这里的输出来自java -version:

java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)

这是结果javac GenericCompilationFailureDemo.java(与上面的代码相同,带有 List、ArrayList 和 Set 的 import 语句):

GenericCompilationFailureDemo.java:30: error: inconvertible types
            (List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets()
;
                                                                              ^
  required: List<Set<? extends GenericCompilationFailureDemo>>
  found:    List<CAP#1>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Set<? extends GenericCompilationFailureDemo> from capture of ?
 extends Set<? extends GenericCompilationFailureDemo>
Note: GenericCompilationFailureDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

这显然是 javac7 的错误。每个铸造转换规则应该允许它 [1]

其中一项规则允许缩小引用转换...然后是未经检查的转换

Casting List<A> => List<B>是本规则允许的

List<A> => List   // narrowing reference conversion
List => List<B>   // unchecked conversion

但这还不是故事的全部。该规范还有进一步的规则来禁止铸造,例如List<String>=>List<Integer>,因为他们是可证明不同的参数化 类型。不存在同时属于这两种类型的对象,因此编译器认为最好不允许这种明显的编程错误。 (您可以通过显式绕过它List<String>=>List=>List<Integer>)

但最后一条规则在这里并不适用;所以它看起来像一个 javac7 bug。

为什么最后一条规则不适用:所以我们正在铸造List<? extends A> to List<A>。这里捕获转换应用于List<? extends A>[2] 所以我们实际上是在选角List<T> to List<A>, where T是一个有上限的新类型变量A.

问题是是否List<T> and List<A> are 可证明不同的参数化类型。我的理解是它是错误的(对于要编译的前两个示例来说它必须是错误的)。自从T是一个类型变量,它可以取一个值List<T> and List<A>相同的参数化类型(即当T=A)。这个推理应该适用于任何类型A.

[1] http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5 http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5

[2] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#341306 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#341306

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么要对 List< 进行泛型转换?将 Set..> 扩展为 List 在 Sun JDK 6 上成功,但在 Oracle JDK 7 上编译失败? 的相关文章

随机推荐

  • 你能在 shell 脚本中生成一个进程吗?

    我试图让我的 bin sh shell 脚本启动另一个应用程序而不暂停执行 也就是说 我正在寻找一种在后台启动它并让我的 shell 脚本继续执行的方法 我希望它能像这样工作 start daemon start success launc
  • 如何使用NamedTemporaryFile(什么时候关闭?)

    我正在尝试编写一系列写入临时文件的函数 然后对写入的文件进行处理 我试图了解该文件是如何处理的 我想做的摘要是 def create function inputs create temp file write some contents
  • JS 私有方法不会在每次构造函数调用时重新定义

    如何创建一个每次调用构造函数时都未定义的 Javascript 私有方法 据我所知 在OOP JS中 私有方法是在 类 的 构造方法 中定义的方法 每次实例化一个新的 对象 时都会调用 我在想也许是一个函数声明 即function name
  • 在 Swift 中使用 obj-c typedef

    我有一个 typedef 如下 typedef NSString VMVideoCategoryType extern VMVideoCategoryType const VMVideoCategoryType MusicVideo ext
  • 组合两个 Runnable 对象

    举例来说 我有一个名为 RunnableA 的 Runnable 它可以执行某些操作 我还有一个名为 RunnableB 的 Runnable 它可以执行其他操作 有没有办法可以将这两个 Runnable 组合起来 以便它们在同一个线程中运
  • Ironpython:函数在 CPython 中工作,IronPython 中神秘的空指针异常

    我正在尝试做一些看起来非常简单的事情 并且属于标准 python 的范围 以下函数接受集合的集合 并返回两个或多个集合中包含的所有项目 为此 虽然集合的集合不为空 但它只是从集合中弹出一个集合 将其与其余集合相交 并更新落在这些交集之一中的
  • 在 React 中测试 mapbox-gl 时如何修复“window.URL.createObjectURL 不是函数”?

    我正在使用 Mapbox material ui 和自定义样式测试 React 组件 我使用 Jest Enzyme 进行测试 我有问题 window URL createObjectURL 不是函数 我读过类似的问题 github com
  • 如何自定义引导侧边栏/sidenav?

    I need to make use of Twitter Bootstrap Sidebar for creating a menu in my web application Highlighted in red To create a
  • 隐藏键盘ios [重复]

    这个问题在这里已经有答案了 我有一些文本输入 每当我触摸背景时 我都可以隐藏键盘 但只有当我输入第一个文本框名称 textField1 时 现在这段代码应该很简单 但我似乎无法理解它 IBAction backgroundTouched i
  • 如何在Python中将词云保存为.png?

    我正在尝试基于字符串创建词云 然后将其导入到报告文档中 我正在使用 python docx matplotlib 和词云 这是我的一个简短的总结 from wordcloud import WordCloud import matplotl
  • 获取 Flask 中的当前用户 ID

    我对 Python 还很陌生 老实说 我对一般编程也很陌生 我目前正在制定一种待办事项列表 我需要它将待办事项放入适当的课程中 所有这些都与教育内容相关 所以 问题很简单 我将其作为 Flask 驱动的路线 app route add co
  • 方案单词列表 eq?

    我有一个问题 我需要查找列表是否等于第二个列表 例如 set eq 1 2 3 1 2 3 gt t set eq 1 2 3 2 3 4 gt f 这些例子在我的程序中是正确的 但这个例子不是 set eq quote quote one
  • 如何使用GridView从服务器获取JSON数据--Flutter

    我参考过食谱 https flutter dev docs cookbook networking fetch data https flutter dev docs cookbook networking fetch data 示例代码是
  • VueJS 自定义 Props 验证功能

    我是 VueJS 的新手 所以我一直在关注他们的官方指南 https v2 vuejs org v2 guide components html Prop Validation 我能够触发前 5 个属性验证器 但我似乎无法触发最后一个示例
  • 在 Firefox 中读取多行内容可编辑文本

    让我们读取一个 contenteditable 元素 span This is editable br Yes it is span 就在您在文本末尾手动添加两个空格之后 I get textContent gt This is edita
  • C++ 中的“new”运算符何时调用构造函数

    自从我开始学习 C 以来 我一直读到 new 运算符在返回指向分配内存的指针之前调用对象的构造函数 因此 出于好奇 我检查了 new 的源代码 并在以下位置找到了以下内容 GLIBCXX WEAK DEFINITION void opera
  • 使用一组字符而不是一个字符的序列对齐算法

    Summary 我从一些有关对齐算法的细节开始 最后我提出了我的问题 如果您了解对齐算法 请从头开始 考虑我们有两个字符串 例如 ACCGAATCGA ACCGGTATTAAC 有一些算法 例如 史密斯 沃特曼 https en wikip
  • R 绘图自定义数据格式变体

    我正在尝试访问customdata通过javascrit分配给每个数据点 例如为每个点分配一个超链接 然而 我注意到数据格式从一个图变为另一个图 这看起来很奇怪 这在本例中完美运行 基于this https stackoverflow co
  • WordPress:single.php 不显示 the_content()

    我正在创建一个自定义 WordPress 主题 但我似乎无法让 single php 模板正常工作 下面是我写的代码 标题出现了 但内容没有出现 有什么想法为什么不是吗 div div id post gt h2 a href title
  • 为什么要对 List< 进行泛型转换?将 Set..> 扩展为 List 在 Sun JDK 6 上成功,但在 Oracle JDK 7 上编译失败?

    下面的代码 class GenericCompilationFailureDemo List