三元运算符如何评估结果数据类型?

Lui*_*ese 3 java ternary-operator type-conversion

鉴于这段代码

public class Main {

    public static void main(String[] args) {
        foo(1);
        foo("1");
        foo(true?1:"1");
        foo(false?1:"1");
    }

    static void foo(int i){System.out.println("int");}
    static void foo(String s){System.out.println("String");}
    static void foo(Object o){System.out.println("Object");}
}
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

int
String
Object
Object

我无法理解为什么在最后两种情况下foo(Object o)调用,而不是foo(int i)和foo(String s).是不是在运行时评估三元表达式的返回类型?

编辑:

令我困惑的是断言

System.out.println((y>5) ? 21 : "Zebra");
Run Code Online (Sandbox Code Playgroud)

编译因为(OCA学习指南 - Sybex):

本的System.out.println()不关心的语句是完全不同的充类型的,因为这既可以转换为字符串

而重点是println被重载以接受Object类型作为输入.相当误导,imho.

Boh*_*ian 10

三元的两种替代方案必须属于同一类型.Integer和String唯一常见的类型是Object,因此操作数都转换为Object,三元组的类型在编译时确定为Object.

然后,编译器使用Object参数静态绑定到该方法.

重要的是,逻辑上三元的结果在编译时是可确定的 - 编译器不能以这种方式工作.它处理表达式和类型.它必须首先解析三元表达式的类型,而不是它的值,并且为此必须首先找到操作数的公共类型.

  • 这里的关键点是重载方法的解析在编译时发生. (2认同)
  • 那么,条件表达式的类型是根据第三和第二个操作数的类型确定的,实际上可能是不同的 (2认同)

Jon*_*eet 7

是不是在运行时评估三元表达式的返回类型?

不,绝对不是.这与Java工作的方式非常相反,其中重载解析等总是在编译时执行.如果您没有将结果传递给方法,但是尝试将其分配给变量,您会发生什么?你会宣布什么样的变量?

表达式的类型受JLS 15.25规则的约束.在两种情况下,第三个操作数都是类型String,导致这是一个引用条件表达式,因此应用表15.25-E,结果为lub(Integer,Object).该lub部分是指JLS 4.10.4,这是相当混乱-这里的类型不完全相同一样只是Object,但在大多数情况下,可以考虑这种方式.