Java 不一致;从int到byte的可能有损转换;编译时错误

Java 不一致;从int到byte的可能有损转换;编译时错误,java,compiler-errors,language-specifications,Java,Compiler Errors,Language Specifications,检查以下代码段: 片段#1 inta=20; int b=30; 字节c=(a>b)?20:30; 错误: 不兼容类型:从int到byte的可能有损转换 字节c=(a>b)?20:30; 片段#2 inta=20; int b=30; 字节h1=70; 字节c=(a>b)?20:h1; 片段#3 inta=20; int b=30; 字节h1=70; 字节h2=89; 字节c=(a>b)?h1:h2; 片段#4 字节c=(真)?20:30; 除了代码片段#1之外,所有这些都可以正常编译

检查以下代码段:

片段#1
inta=20;
int b=30;
字节c=(a>b)?20:30;
错误:
不兼容类型:从int到byte的可能有损转换
字节c=(a>b)?20:30;
片段#2
inta=20;
int b=30;
字节h1=70;
字节c=(a>b)?20:h1;
片段#3
inta=20;
int b=30;
字节h1=70;
字节h2=89;
字节c=(a>b)?h1:h2;
片段#4
字节c=(真)?20:30;
除了代码片段#1之外,所有这些都可以正常编译。这种行为如何被证明是正当的?如果代码段1产生“可能的有损转换”错误,那么代码段2和4也应该产生错误,因为它们仍然包含
int
类型的文本。为什么编译成功?

解释了这种行为

片段#1:

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

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

片段#2:

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

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

片段#3:

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

第二个和第三个操作数都是
字节
,因此表达式的类型是
字节
,可以将其分配给
字节
变量

片段#4:


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

中描述了此行为


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

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

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


案例2令我惊讶:我本以为它也会失败,因为int操作数会导致条件表达式为int类型

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

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

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


情况4也由用于情况1和3的“同类型操作数规则”描述;然而,该条件现在是常数这一事实使其成为一个问题

int类型的常量表达式在分配给更窄类型的变量时会隐式缩小,如中所述:

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


如果将
int
更改为
final int
(常数),编译器将看到
a
b
的值在字节范围-128..127内。对于int变量,编译器不进行此类计算,并假设int可能会溢出字节范围。@JoopEggen但为什么a和b的范围很重要,甚至是它们的数据类型;(a>b)是一个条件,其计算结果将为真或假,并根据该条件将20或30分配给变量c。我不明白为什么变量a和b的范围和类型应该重要。重要的是我们用来分配给变量c的文本20和30或变量h1和h2的范围和数据类型。但从代码4来看,变量a和b的数据类型和范围很重要。当将较大类型的变量分配给较小类型的变量时,通常会出现警告/错误,以防意外丢失信息。但我希望有更好的答案来澄清java的状态