三元运算符的两个右手表达式必须是兼容的类型吗?

Posted

技术标签:

【中文标题】三元运算符的两个右手表达式必须是兼容的类型吗?【英文标题】:Must both right-hand expressions of a ternary operator be of compatible types? 【发布时间】:2018-11-13 03:08:00 【问题描述】:

My Practice Tests book 包含这个关于三元运算符的问题:

// What is the output of the following application?
public class Transportation 
    public static String travel(int distance) 
        return(distance < 1000 ? "train" : 10);
    
    public static void main(String[] args) 
        travel(500);
    

它不会编译。给出的解释如下:

三元运算要求两个右手表达式都是 兼容的数据类型。在这个例子中,第一个右手 外部三元运算的表达式是字符串类型,而 第二个右手表达式是 int 类型。由于这些数据类型 不兼容,代码无法编译,选项 C 是 正确答案。

真的是这个原因吗?在我看来,这个示例无法编译,因为 10 不是字符串,而字符串是方法必须返回的内容。 我问是因为 System.out.println(distance &lt; 1000 ? "train" : 10); 编译和运行没有问题。

【问题讨论】:

这也很有趣:***.com/questions/8002603/… 您认为“不兼容的数据类型”和“10 不是String”之间到底有什么区别? @EJP 这样说没有区别。问题是教科书的答案对以下解释是开放的:“第一个右手表达式必须与第二个兼容,第二个必须与第一个兼容。” @mgr326639 还有什么其他的说法吗?这些类型必须相互兼容。他们不是。您的“以下解释”说的完全一样。 "类型必须相互兼容"。不,他们没有,我的System.out.println 示例证明了这一点。这就是我问题的重点。两个右手表达式中的每一个都必须与函数的返回类型兼容(在本例中恰好是 String)。教科书的答案可以双向解释,这就是我认为它模棱两可的原因。 【参考方案1】:

您的方法声明返回类型为String。任何return 语句都必须生成与声明的返回类型兼容的表达式。

然而,在这种情况下,返回类型可以是int,这就解释了为什么编译器会拒绝它。

这不是特定于三元运算符,它也可以用等效的 if/else 块重现:

if(distance < 1000)
   return "train"; //This part is valid
else
    return 10; //This line will be rejected by the compiler

出于同样的原因,最后一行将无法编译。这仅仅是因为基本的类型检查。

System.out.println(距离

这是因为编译器检测到Stringint 的共同类型,即Object,并决定选择此签名:

java.io.PrintStream#println(Object x) // available in the target class

但是,这不适用于方法返回类型。

如果您将返回类型更改为Object,您的代码也会编译。但这当然不是你想要做的。

三元运算要求两个右手表达式的数据类型兼容

-> 这部分实际上是有效的。这是一种解释方式:每个这两个表达式必须单独兼容:

String value = distance > 1000 ?
                 "train" //this must be compatible with String
                 :
                 10 //this too must be compatible with String (it isn't)

相比之下:

Object value = distance > 1000 ?
                 "train" //this must be compatible with Object (it is)
                 :
                 10 //this too must be compatible with Object (it is)

换句话说,对System.out.println(distance &lt; 1000 ? "train" : 10) 的调用类似于上面的最后一个示例,其中预期的类型与两个表达式都兼容。

【讨论】:

"这是因为编译器检测到String和int都有一个共同的类型,即Object"是原教科书声明"都是右手的原因具有兼容数据类型的表达式” 是没有意义的,因为一切(至少在装箱之后)最终都是 Object,所以一切都是“兼容的”。 @luk2302 实际上是对的。但是当涉及到方法签名解析(println 调用)时,书中的那句话可能需要稍微改写一下,但想法是相似的。我已经用更多信息编辑了答案,以说明区别是什么。 并不是说int 只兼容Object 通过装箱到Integer This part is in fact valid. here's a way to interpret it:... 我不认为如果可以推断出真相,那么声明是有效的,但前提是以正确的方式解释它。当我第一次阅读教科书答案时,我考虑了歧义,但当我到达Since these data types are incompatible 部分时将其丢弃。注意复数形式。我的理由是:由于 String 并非不兼容,它们不可能表示“单独”。所以他们的意思必须是“彼此之间”。您是否同意可以改进教科书答案的措辞以减少歧义?【参考方案2】:

真的是这个原因吗?在我看来,这个示例无法编译,因为 10 不是字符串,而字符串是方法 必须返回

你的推理和作者的回答都是对的。 我认为你的问题的正确答案是他们的联合。

1) 三元运算符无效

因为

2) 在当前上下文中,您分配给它的类型:int 不能分配给 String

您可以通过编译器发出的错误消息来检查它。

在这里,您必须考虑:

return(distance < 1000 ? "train" : 10);

作为编译器评估的两件事:

1) distance &lt; 1000 ? "train" : 10 // 产生结果

2) returns (the produced result); // 根据方法返回类型返回应该可以赋值给String的结果

其实是编译错误:

Transportation.java:3:错误:不兼容的类型:错误类型 条件表达式 返回(距离 int 不能转成字符串

指两个错误:条件表达式错误及其原因:int与String不兼容的错误

因此,只有当三元在编译时有效时,才会出现 return 中的 int 和 String 之间不兼容的编译错误。

编写一个有效的三元表达式,您会看到编译器只会发出关于return 语句的错误信号:

public static String travel(int distance) 
    return(distance < 1000 ? 15 : 10);

错误:不兼容的类型:int 无法转换为 String

【讨论】:

【参考方案3】:

你是对的,解释是混乱的,因为不同的兼容类型可以用于右手表达式。

您可以根据第二个和第三个操作数here的类型找到条件表达式的结果类型表。

如this question 中所述,可以有一些数字类型的类型转换。

【讨论】:

以上是关于三元运算符的两个右手表达式必须是兼容的类型吗?的主要内容,如果未能解决你的问题,请参考以下文章

三元运算符

JavaScript逻辑运算符 三元表达式

三元运算符

Java连载18-引用数据类型三元运算符控制语句if

13 三元运算符 及 运算符优先级

具有不同类型表达式的三元运算符[重复]