Java 三元运算符如何计算结果数据类型?

Java 三元运算符如何计算结果数据类型?,java,type-conversion,ternary-operator,Java,Type Conversion,Ternary Operator,考虑到这段代码 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)

考虑到这段代码

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");}
}
这是我得到的输出:

int String Object Object 编译原因(OCA研究指南-Sybex):

System.out.println()不关心语句是否是完全不同的类型,因为它可以将两者转换为字符串


问题是println被重载以接受对象类型作为输入。很容易引起误解,伊姆霍。

三元合金的两种替代品必须是同一类型的。整数和字符串的唯一常见类型是Object,因此操作数都转换为Object,三元数的类型在编译时确定为Object

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

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

三元表达式的返回类型不是在运行时计算的吗

不,绝对不是。这与Java的工作方式截然不同,Java总是在编译时执行重载解析等。如果没有将结果传递给方法,但尝试将其分配给变量,您会期望发生什么?您会声明哪种类型的变量


表达式的类型由的规则控制。在这两种情况下,第三个操作数的类型均为
String
,因此这是一个参考条件表达式,因此应用表15.25-E,结果为
lub(整数,对象)
lub
部分指的是,这相当令人困惑-这里的类型与
对象不完全相同,但在大多数情况下可以这样考虑。

我想,这是对其他答案的补充。(尤其是对于那些想理解迂腐答案的人来说。)

引用类型的三元条件的结果最终是
lub(trueType,falseType)
,因此在这种特殊情况下,它是
lub(Integer,String)

一组引用类型的最小上界或“lub”是比任何其他共享超类型更具体的共享超类型[…]

为了理解lub
,我们可以对简单类型的算法做一种“scratch”版本,如下所示

首先,为每种类型制作一张表格。在一列中,写下超类层次结构,在另一列中,写下所有实现的接口:

+------------------------+------------------------+
|      Integer           |       String           |
+------------------------+---------+--------------+
| classes |  interfaces  | classes |  interfaces  |
+------------------------+---------+--------------+
| Object  | Serializable | Object  | Serializable |
| Number  | Comparable   | String  | Comparable   |
| Integer |              |         | CharSequence |
+---------+--------------+---------+--------------+
lub(Integer, String) =
    Object & Serializable & Comparable
除了这里的
lub
有点复杂,因为
compariable
。从技术上讲,
lub(Integer,String)
产生一个无限类型,因为我们需要再次(无限地)执行
lub(Integer,String)
,以便将类型参数设置为
Comparable

lub(Integer, String) =
    Object & Serializable & Comparable<? extends lub(Integer, String)>
lub(整数,字符串)=

Object&Serializable&CompariableOverload分辨率始终在编译时确定。@Radiodef OP询问为什么三元运算符的结果是
Object
,而不是
int
String
。@Luigimendoza为什么它应该是
int
String
而不是
对象
?OP声明他们认为应该在运行时评估该类型,但事实并非如此。因此,如果结果是
int
String
,则必须在编译时对条件进行评估,对于大多数情况,这是不可能的。考虑到我之前的评论,程序的行为应该是合理的。是的,你是正确的,这本书误导了你。@LouisWasserman,这不是唯一的误导信息。。。再来一个,我就放火了!这是Oracle自己提出的…这里的关键点是重载方法的解析发生在编译时。好的,条件表达式的类型是根据第三个和第二个操作数的类型来确定的,对于“如果没有将结果传递给方法,但尝试将其分配给变量,您会期望发生什么?“嗯,这是有道理的。。。我试图通过阅读那一段来找到答案,但我仍然有点困惑,因为润滑油的规则非常密集。不过,在我看来,开头一句解释得相当清楚一组引用类型的最小上界或“lub”是一个比任何其他共享超类型都更具体的共享超类型。老实说,我不会声明任何变量,因为我从来没有使用过这种形式。但是认证,你知道…@Radiodef:我在寻找定义,但找不到它。。。它在哪里?(我以前读过,但现在找不到…)
lub(Integer, String) =
    Object & Serializable & Comparable
lub(Integer, String) =
    Object & Serializable & Comparable<? extends lub(Integer, String)>