三元运算符的两个右手表达式必须是兼容的类型吗?
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 < 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(距离
这是因为编译器检测到String
和int
的共同类型,即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 < 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 < 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 中所述,可以有一些数字类型的类型转换。
【讨论】:
以上是关于三元运算符的两个右手表达式必须是兼容的类型吗?的主要内容,如果未能解决你的问题,请参考以下文章