Java 不一致;从int到byte的可能有损转换;编译时错误
检查以下代码段: 片段#1Java 不一致;从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之外,所有这些都可以正常编译
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的状态