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)>