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

检查以下代码段:

片段 #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


答案 1

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

片段 #1:

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

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

片段 #2:

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

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

片段 #3:

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

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

片段 #4:

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


答案 2

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


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

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

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


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

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

如果其中一个操作数是 T 类型,其中 Tis 是字节、短整型或字符,而另一个操作数是 int 类型的常量表达式 (§15.28),其值可在类型 T 中表示,则条件表达式的类型为 T。

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


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

当赋值到较窄类型的变量时,int 类型的常量表达式将隐式缩小,如赋值上下文中所述:

如果变量的类型为 byte、short 或 char,并且常量表达式的值可在变量的类型中表示,则可以使用窄基元转换。


推荐