不一致的“从int到字节的可能的有损转换”编译时错误

时间:2019-05-16 07:22:17

标签: java compiler-errors language-specifications

检查以下代码段:

代码段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;

除了代码片段1以外,所有这些都可以编译。如何证明这种行为合理?如果代码片段1产生“可能的有损转换”错误,则代码片段2和4也应该给出,因为它们仍包含类型int的文字。他们为什么编译成功?

2 个答案:

答案 0 :(得分:28)

J.L.S 15.25.解释了此行为。

代码段1:

  

如果第二个操作数和第三个操作数具有相同的类型(可能为空类型),则这是条件表达式的类型

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

代码段2:

  

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

一个操作数是byte,另一个是int文字,其值可以表示为byte,因此表达式的类型为byte,可以被分配给byte变量。

代码段3:

  

如果第二个操作数和第三个操作数具有相同的类型(可能为空类型),则这是条件表达式的类型

第二个操作数和第三个操作数均为byte,因此表达式的类型为byte,可以将其分配给byte变量。

代码段4:

由于所有3个操作数都是常量,因此整个三元表达式都是常量表达式,因此编译器将此表达式视为简单的赋值-byte c = 20;-有效。

答案 1 :(得分:8)

此行为在language spec中进行了描述。


案例1和3的描述相同:

  

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

在情况1中,操作数的类型为int,因此整个表达式的类型为int,因此不兼容。在情况3中,类型为byte的操作数,因此结果是兼容的。


第2种情况对我来说是令人惊讶的:我本来也希望失败,因为int操作数会导致条件表达式为int类型。

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

  

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

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


第4种情况也通过第1种情况和第3种情况使用的“相同类型的操作数”进行了描述;但是,条件现在不变的事实使其成为constant expressions

Assignment contexts中所述,将int类型的常量表达式分配给较窄类型的变量时会隐式缩小其范围:

  

如果变量的类型为byte,short或char,并且常量表达式的值可以表示为变量的类型,则可以使用缩窄的原始转换。