具有不同类型表达式的三元运算符[重复]
Posted
技术标签:
【中文标题】具有不同类型表达式的三元运算符[重复]【英文标题】:Ternary operator with different types of expressions [duplicate] 【发布时间】:2021-12-18 10:40:09 【问题描述】:我在玩三元运算符时发现了一些奇怪的东西。我有以下代码:
class Main
static void foo(int a)
System.out.println("int");
static void foo(String a)
System.out.println("String");
static void foo(Object a)
System.out.println("object");
public static void main(String[] args)
foo(2==3 ? 0xF00:"bar");
System.out.println((2==3 ? 0xF00:"bar").getClass().getName());
结果
对象
java.lang.String
第一行结果表明该指令以对象参数传递给foo方法。
指令本身产生String的第二行。
问题:
为什么如果结果是 String 编译器决定使用 Object?
这是因为类型不明确吗?
如果是,那么为什么返回类名java.lang.String?
【问题讨论】:
您混淆了运行时和编译时类型。(Object)"foo"
的类型在编译时为Object
,在运行时为String
。
(2==3 ? 0xF00:"bar")
产生字符串(“bar”),然后getClass()
on
将println(a)
添加到foo(Object)
,它将打印String
“栏”。
【参考方案1】:
如果对阅读不感兴趣,可以跳到摘要。
请参阅此处的 JavaDoc:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25
低于 15.25.3。参考条件表达式上面写着:
条件表达式的类型是 应用捕获转换的结果
捕获转换:https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.10
总结:
对于类型确定,使用捕获转换,其中对于您的示例,首先将 int 装箱为 Integer,然后获取最接近的 Integer 和 String 的公共超类,即 Object 类。所以条件表达式的类型是Object,所以会调用以Object为参数的方法。
现在对于第二部分,首先评估条件运算符,然后将其拆箱,然后评估 .getClass()。所以它会打印 java.lang.String。
这也记录在这里:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25
15.25 岁以下。条件运算符 ? :
在运行时,条件的第一个操作数表达式 首先计算表达式。如有必要,拆箱转换是 对结果执行。
【讨论】:
【参考方案2】:在Java 中,您有编译时间 类型信息和运行时间 类型信息。编译时类型信息是编译器可以通过查看值或表达式的类型推断出它,而不是执行它。当编译器看到表达式时
2 == 3 ? 0xF00 : "bar"
它不知道2 == 3
是真还是假,因为它不执行代码。所以它只知道结果可以是Integer
,或String
。因此,当需要选择调用哪个foo
方法时,它会选择接受Object
的方法,因为它知道在这两种情况下都可以使用的唯一方法。
但是,当代码实际运行时,2 == 3
将为 false,结果将是一个String
,其getClass()
方法将返回String.class
。这就是您需要注意的:getClass()
不会返回变量在编译时所具有的类型,而是返回变量在运行时所拥有的对象的实际类型。即
Object o = "Hello!";
System.out.println(o.getClass());
将打印java.lang.String
,因为即使对于编译器来说它是一个Object
,在运行时它实际上是一个String
。
【讨论】:
【参考方案3】:在编译阶段,编译器注意到2 == 3 ? 0xF00 : "bar"
的结果可能是int 或String。为了兼容两者,它决定调用foo(Object a)
。
在运行时,2 == 3 ? 0xF00 : "bar"
的结果是 String bar
。
【讨论】:
int 先装箱。以上是关于具有不同类型表达式的三元运算符[重复]的主要内容,如果未能解决你的问题,请参考以下文章