30

检查以下代码片段:

片段#1

int a=20;
int b=30;
byte c= (a>b)? 20:30;
Error:
incompatible types: possible lossy conversion from int to byte
byte c= (a>b)? 20:30;

片段#2

int a=20;
int b=30;
byte h1=70;
byte c= (a>b)? 20:h1;

片段#3

int a=20;
int b=30;
byte h1=70;
byte h2=89;
byte c= (a>b)? h1:h2;

片段#4

byte c= (true)? 20:30;

除了 Snippet #1 之外,所有这些都编译得很好。这种行为如何合理?如果 Snippet #1 产生“可能的有损转换”错误,那么 Snippet #2 和 4 也应该,因为它们仍然包含 type 的文字int。为什么它们编译成功?

4

2 回答 2

30

JLS 15.25。解释了这种行为。

片段#1:

如果第二个和第三个操作数的类型相同(可能是 null 类型),那么那就是条件表达式的类型

第二个和第三个操作数都是int文字,因此表达式的类型也是int,如果没有显式强制转换,它不能分配给byte变量。因此编译错误。

片段#2:

如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式(第 15.28 节),其值可在类型 T 中表示,则条件表达式的类型为T。

一个操作数是 a byte,另一个是一个int字面量,它的值可以表示为byte,所以表达式的类型是byte,可以赋值给一个byte变量。

片段#3:

如果第二个和第三个操作数的类型相同(可能是 null 类型),那么那就是条件表达式的类型

第二个和第三个操作数都是byte,所以表达式的类型是byte,可以赋值给一个byte变量。

片段#4:

由于 3 个操作数都是常量,整个三元表达式就是一个常量表达式,所以编译器把这个表达式当作一个简单的赋值 - byte c = 20;- 是有效的。

于 2019-05-16T07:47:28.333 回答
7

此行为在语言规范中进行了描述。


案例 1 和 3 由同一点描述:

如果第二个和第三个操作数的类型相同,那么这就是条件表达式的类型。

第一种情况,操作数是int类型,所以整体表达式是int类型,所以不兼容。在情况 3 中,操作数为 byte 类型,因此结果是兼容的。


案例 2 让我感到惊讶:我本来预计它也会失败,因为 int 操作数会导致条件表达式为 int 类型。

但是,以下几点描述了此行为:

如果其中一个操作数是 T 类型,其中 Ti 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式(第 15.28 节),其值可在类型 T 中表示,则条件表达式的类型为 T .

20 是一个适合字节的常量表达式,因此结果是一个字节。


情况 4 也由用于情况 1 和 3 的“相同类型的操作数规则”来描述;但是,条件现在是常量的事实使其成为常量表达式

当分配给更窄类型的变量时,int 类型的常量表达式被隐式缩小,如分配上下文中所述:

如果变量是 byte、short 或 char 类型,并且常量表达式的值可以在变量的类型中表示,则可以使用缩小原语转换。

于 2019-05-16T07:49:18.527 回答