Java 8 中三元运算符的泛型编译错误,但 Java 7 中没有

2024-01-05

该类在 Java 7 中编译正常,但在 Java 8 中编译失败:

public class Foo {

    public static void main(String[] args) throws Exception {
        //compiles fine in Java 7 and Java 8:
        Class<? extends CharSequence> aClass = true ? String.class : StringBuilder.class;
        CharSequence foo = foo(aClass);

        //Inlining the variable, compiles in Java 7, but not in Java 8:
        CharSequence foo2 = foo(true ? String.class : StringBuilder.class);

    }

    static <T> T foo(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }
}

编译错误:

错误:(9, 29) java: 类 Foo 中的方法 foo 无法应用于给定 类型;必需:java.lang.Class 找到:true ? Str[...]类
原因:推断的类型不符合等式约束 推断:java.lang.StringBuilder 等式约束:java.lang.StringBuilder、java.lang.String

为什么这在 Java 8 中停止工作了?这是故意的/其他功能的副作用,还是只是一个编译器错误?


我要冒险说这个错误(虽然它可能符合也可能不符合更新的 JLS,我承认我没有详细阅读)是由于 JDK 的类型处理不一致造成的8 编译器。

一般来说,三元运算符使用与双参数方法相同的类型推断,该方法的形式参数都基于相同的类型参数。例如:

static <T> T foo(Class<? extends T> clazz, Class<? extends T> clazz2) { return null; }

public static void main(String[] args) {
    CharSequence foo2 = foo(String.class, StringBuilder.class);
}

在这个例子中,T可以推断为捕获? extends Object & Serializable & CharSequence。现在类似地,在 JDK 7 中,如果我们回到原来的示例:

CharSequence foo2 = foo(true ? String.class : StringBuilder.class);

这与上面几乎完全相同的类型推断,但在这种情况下,将三元运算符视为这样的方法:

static <T> T ternary(boolean cond, T a, T b) {
    if (cond) return a;
    else return b;
}

所以在这种情况下,如果您传递 String.class 和 StringBuilder.class 作为参数,则 T 的推断类型是(粗略地说)Class<? extends Object & Serializable & CharSequence>,这就是我们想要的。

事实上,您可以用此方法替换原始代码片段中三元运算符的使用,因此:

public class Foo {

    public static void main(String[] args) throws Exception {
        //compiles fine in Java 7 and Java 8:
        Class<? extends CharSequence> aClass = true ? String.class : StringBuilder.class;
        CharSequence foo = foo(aClass);

        //Inlining the variable using 'ternary' method:
        CharSequence foo2 = foo(ternary(true, String.class, StringBuilder.class));

    }

    static <T> T foo(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }

    static <T> T ternary(boolean cond, T a, T b) {
        if (cond) return a;
        else return b;
    }
}

... And now it compiles in Java 7 and 8 (edit: actually it also fails with Java 8! edit again: it now works, Jdk 8u20). What gives? for some reason an equality constraint is now being imposed on T (in the foo method), rather than a lower-bounds constraint. The relevant section of the JLS for Java 7 is 15.12.2.7 http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.7; for Java 8 there's a whole new chapter on type inference (chapter 18 http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html).

Note that explicitly typing T in the call to 'ternary' does allow compilation with Java 7 and 8, but this doesn't seem like it should be necessary. Java 7 does the right thing, where Java 8 gives an error even though there is an appropriate type that can be inferred for T.

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

Java 8 中三元运算符的泛型编译错误,但 Java 7 中没有 的相关文章

  • HibernateTemplate 可以与 EntityManager 共存吗?

    我们有一个 spring 3 应用程序 它仍然使用已弃用的HibernateTemplate为了持久性并希望迁移到更现代的 JPAEntityManager 是否可以在迁移过程中并行使用这两个 API 甚至可能在单个事务中同时使用 以便我们
  • Typescript 从传递的函数返回类型推断返回类型

    我可能正在尝试实现不可能的目标 但事情就这样了 我想定义一个函数 function A 它将返回与传递给函数 A 的参数的新函数相同的类型 e g export function test
  • 使用 ScriptEngine 从 JavaScript 调用 Java 方法

    我正在使用 ScriptEngine 运行 JavaScript 我希望 JavaScript 脚本能够调用 myFunction 其中 myFunction 是我的给定类中的一个方法 我知道可以将 importPackage 用于标准 J
  • Javadoc 链接到其他类中的方法

    目前我正在使用以下 Javadoc 语法引用其他类中的方法 see link com my package Class method 据我从文档中了解到 这是执行此操作的正确方法 但现在到了有趣的部分 或者说令人沮丧的部分 当我生成这个 j
  • 将 Swing 集成到简单的文本冒险游戏中

    我对 Java 中的一些中级概念相当陌生 最近 我制作了一款名为 DazzleQuest 的文本冒险游戏 它完全在开发者控制台 终端中运行 它涉及到我的朋友作为角色 所以我想向他们展示它 并通过将命令行的功能和控制台的输出转移到一个简单的
  • 在 Selenium Grid 中注册 PhantomJS 节点时出错

    我有以下问题 我成功启动了 Selenium Grid hub java jar selenium server standalone 2 53 0 jar role hub 之后我尝试使用以下命令启动 PhantomJS 节点 phant
  • Java TCP Echo 服务器 - 广播

    我有一个简单的回显服务器 我希望当连接的用户向服务器键入任何内容时 所有其他客户端和该客户端都会收到消息 MOD 它现在不会发送给所有客户端 但它应该发送 而且我只是不知道我的代码出了什么问题 所以现在它只会将消息 MOD 发送给发送消息的
  • Runtime.getRuntime().exec(cmd) 挂起

    我正在执行一个命令 该命令返回文件的修订号 文件名 但如果执行命令时出现问题 应用程序就会挂起 我可以做什么来避免这种情况 请在下面找到我的代码 String cmd cmd C si viewhistory fields revision
  • 使用 PowerMock 和 TestNG 模拟单个静态方法

    class StaticClass public static String a return a public static String ab return a b 我想嘲笑StaticClass a以便它返回 x 并致电StaticC
  • 无法从 PDFA1-a 格式文档中提取图像

    我正在使用以下代码从 PDFA1 a 格式的 pdf 中提取图像 但我无法获取图像 List
  • 在字节数组上进行右位旋转/循环移位的最快方法是什么

    如果我有数组 01101111 11110000 00001111 111 240 15 移位 1 位的结果是 10110111 11111000 00000111 183 248 7 数组大小不固定 移位范围为 1 到 7 含 目前我有以
  • 错误:类 kotlin.reflect.jvm.internal.FunctionCaller$FieldSetter

    我已尝试一切方法来消除此错误 但它不断出现 Class kotlin reflect jvm internal FunctionCaller FieldSetter can not access a member of class com
  • 在Linux中执行jar文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我创建了一个可执行的 Java jar 文件 也就是说 我将 java 程序正确打包到 jar 文件中 包括 META INF MANIFEST 文件
  • GSSAPI 中的 javax.naming.AuthenticationException

    我正在尝试使用 JAVA GSSAPI 执行 NTLM 绑定 我收到此错误 javax naming AuthenticationException GSSAPI 根异常是 javax security sasl SaslException
  • 将 JPanel 添加到 JFrame

    我有一个程序 其中将 JPanel 添加到 JFrame public class Test Test2 test new Test2 JFrame frame new JFrame Test frame setLayout new Bor
  • 在服务器上创建 Zip 文件并使用 java 下载该 zip

    我从 mkyong 获得了以下代码 用于在本地压缩文件 但是 我的要求是在服务器上压缩文件并需要下载它 任何人都可以帮忙吗 代码写入zip文件 public void zipFiles File contentFile File navFi
  • 如何在 Windows 上使用 Java Hotspot JVM 禁用小型转储 (mdmp) 文件生成

    目前 我有一个已部署的可执行 jar 文件 该文件在崩溃时会创建大型 7 Gb 小型转储文件 我想要一个导致崩溃原因的文本表示 而不是 JVM 状态的二进制文件 我尝试使用中找到的信息这个 CodeRanch 帖子 http www cod
  • Java:易失性足以使类线程安全?

    我有一个关于 Java 中 volatile 语句的问题 请看这个构造的例子 class Master Foo is a class with thread safe methods public volatile Foo foo clas
  • 如何在不下载子项的情况下从 Firebase 获取子项密钥?

    我有一个 Firebase 数据库 其中的节点 items 有很多子项 我想导入子项键的列表 由于每个子项都包含相当多我对此不感兴趣的数据 因此我想仅下载子项密钥 以最大程度地减少传输的数据量 为了便于说明 假设我有以下数据结构 然后我想获
  • Java Media API:java media api 下载

    我在哪里可以找到javax media jar 文件 在sun站点它下载一个安装程序 有没有可用的java媒体jar 没有 javax media 具体是 jar 文件 该包位于 jmf jar 文件中 您需要运行安装程序并取出 jar 或

随机推荐