当前位置: 首页 > 面试题库 >

JDK 7中泛型和三元运算符的编译错误

葛志国
2023-03-14
问题内容

我在编写一些Java代码时遇到了编译失败,我将其简化为以下测试用例:

import java.util.Collections;
import java.util.List;

public class TernaryFailure {
    public static List<String> thisWorks() {
        return Collections.emptyList();
    }

    public static List<String> thisFailsToCompile() {
        return true ? Collections.emptyList() : Collections.emptyList();
    }
}

上面的代码无法javac使用JDK 1.7.0_45 进行编译:

$ javac TernaryFailure.java
TernaryFailure.java:10: error: incompatible types
        return true ? Collections.emptyList() : Collections.emptyList();
                    ^
  required: List<String>
  found:    List<Object>
1 error

但是,使用JDK 1.8.0_05编译时不会出现任何错误。

这是Java 7实现中的错误吗?还是对Java 8中的Java语言规范进行了增强以开始允许这样做-如果是这样,有什么变化?


问题答案:

JLS SE
8在(§15.2)中说:

当某些表达式出现在某些上下文中时,它们被视为多表达式。以下形式的表达式可以是多边形表达式:

  • 带括号的表达式(第15.8.5节)

  • 类实例创建表达式(第15.9节)

  • 方法调用表达式(第15.12节)

  • 方法引用表达式(第15.13节)

  • 条件表达式(第15.25节)

  • Lambda表达式(§15.27)

因此,从规范的这一部分可以清楚地看出,条件表达式(即三元运算符)可以视为多表达式。但是,并非所有条件表达式都可以视为多表达式,只能引用根据(§15.25)的条件表达式。(§15.25.3)阐明了可以将参考条件表达式视为多表达式的条件:

如果引用条件表达式出现在分配上下文或调用上下文中(第5.2节至第5.3节),则它是一个多边形表达式。否则,它是一个独立的表达式。

当多引用条件表达式出现在目标类型为T的特定种类的上下文中时,其第二和第三操作数表达式类似地出现在目标类型为T的相同种类的上下文中。

多边形引用条件表达式的类型与其目标类型相同。

检查示例中条件表达式是否出现在赋值上下文中,因为根据(§14.17):

当带有表达式的return语句出现在方法声明中时,该表达式必须可分配给该方法的声明返回类型(第5.2节),否则会发生编译时错误。

那么到最后,这意味着什么?这意味着,当条件表达式为多边形表达式时,目标类型将“推入”到每个操作数中。这样,编译器可以将条件的每个部分归于目标。您的目标是List<String>。如果我们检查emptyList()方法的定义,我们将:

@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

因此,使用target List<String>,编译器可以推断出T == String且代码已被接受。



 类似资料:
  • 问题内容: 为什么会产生错误,应如何写? 错误是“找不到<接受提供的参数的重载” 问题答案: 您的三元运算符在那里不工作的 原因 是由于各种中缀运算符的优先级。您可以在此处查看运算符优先级列表。如果您看一下,会发现底部的运算符通常是放置在较大代码段之间的运算符。优先级越高,它将越紧紧抓住左侧(或右侧)的表达式。因此,您通常希望您的运算符具有非常低的关联性,因此在类似以下的表达式中: 该会抢在它两侧

  • 问题内容: 此类在Java 7中可以编译,但在Java 8中不能编译: 编译错误: 错误:(9,29)java:类Foo中的方法foo无法应用于给定类型;必需:java.lang.Class找到:true吗?str […]类 原因:推断的类型不符合相等的约束推断的:java.lang.StringBuilder相等约束:java.lang.StringBuilder,java.lang.Strin

  • 问题内容: 为什么编译正常但有错误?(更确切地说, “类型不匹配:无法从List 转换为List ” ) 我本以为两个函数都可以编译为相同的字节码,所以一个聪明的编译器应该为… 推断正确的类型。 问题答案: 我可以在Java 8中正常编译。 Java的早期版本可能需要更多帮助 应该管用。 编辑 这是由于Java 8类型推断的改进,如此处所述 http://openjdk.java.net/jeps

  • 条件(三元)运算符是 JavaScript 仅有的使用三个操作数的运算符。一个条件后面会跟一个问号(?),如果条件为 truthy ,则问号后面的表达式A将会执行;表达式A后面跟着一个冒号(:),如果条件为 falsy ,则冒号后面的表达式B将会执行。本运算符经常作为 if 语句的简捷形式来使用。(MDN) 三元运算符,也称条件运算符、三目运算符。 三元运算符可以代替简单的 if 语句。 1. 语

  • 据我所知,PowerShell似乎没有一个针对所谓三元运算符的内置表达式。 例如,在支持三元运算符的C语言中,我可以编写如下内容: 如果PowerShell中并不存在这种情况,那么实现相同结果的最佳方法(即易于阅读和维护)是什么呢?