繁体   English   中英

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

[英]Compilation error with generics and ternary operator in JDK 7

编写一些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),则它是一个多表达式。 否则,它是一个独立的表达式。

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

多参考条件表达式的类型与其目标类型相同。

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

当带有Expression的return语句出现在方法声明中时,Expression必须可赋值(第5.2节)到方法的声明返回类型,否则会发生编译时错误。

那么在一天结束时,这一切意味着什么? 这意味着当条件表达式是多表达式时,目标类型被“下推”到每个操作数。 这样,编译器可以将条件的每个部分与目标相关联。 在您的情况下,目标是List<String> 如果我们检查emptyList()方法的定义,我们有:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM