类型不匹配:无法使用三元运算符将int转换为byte

3

我正在开发一个利用字节数组操作的项目,我试图写出类似于以下的代码:

boolean enabled = getEnabled();

byte enabledByte = enabled ? 0x01 : 0x00; // compile error

我遇到的问题是无法编译上述内容。

类型不匹配:无法将 int 转换为 byte

但是,如果我将它扩展为以下内容,则可以正常工作:
boolean enabled = getEnabled();

byte enabledByte;
if (enabled) {

    enabledByte = 0x01;
} else {

    enabledByte = 0x00;
}

我的问题是

为什么我无法在短if语句中使用字节赋值?


另外有趣的是:为什么 byte enabledByte = true ? 0x01 : 0x00; 可以编译通过? - ldz
1
@ldz 这是因为 true ? 0x01 : 0x00 是一个常量表达式,不同于使用变量而非 true 字面值的情况。请参考我的答案,了解语言规范如何规定这一点。 - M A
4个回答

2
数字字面量自然是int类型,而不是byte类型。该语言有一个特殊的从数字字面量(< 128)到byte的隐式转换,因此您的第二个示例不需要强制转换。但是,将字面量包装在条件运算符中会创建一个int类型的表达式,它不是字面量,因此您需要强制转换。

2

0x000x01int字面量:它们是带有int类型的表达式。通常情况下,int不能被赋值给byte,但如果表达式是编译时常量,并且值在byte的范围内,则可以进行赋值。

使用条件语句,分配的值是编译时常量:

if (enabled) {
  enabledByte = 0x01;
} else {
  enabledByte = 0x00;
}

这些赋值语句在编译器的角度来看是完全独立的。有一个语句将常量值1赋给变量,另一个语句将常量值0赋给变量。
对于每个语句,编译器可以保证其适合字节范围内,因此它会自动将被赋值的值缩小为字节。
然而,使用条件运算符的赋值语句:
enabledByte = enabled ? 0x01 : 0x00;

rhs表达式的类型为int,但因为enabled在编译时不可知,所以它不是编译时常量。两个可能的值都是编译时常量,并且都适合于一个byte,但非常量的第一个操作数使其不是常量。因此,条件运算符表达式的结果不能自动缩小。
最有效的解决方案是将第二个和第三个操作数转换为byte
enabled ? (byte) 0x01 : (byte) 0x00

这比那更好。

(byte) (enabled ? 0x01 : 0x00)

由于后者在运行时会进行强制类型转换,每次表达式被评估时都会进行转换,而前者不会:操作数已经是字节码在编译时,因此不需要进行类型转换。


0

你需要至少一个强制类型转换来将三元表达式转换为 byte,由于三元表达式的缘故,它默认为 int

byte enabledByte = enabled ? (byte) 0x01 : 0x00; 

如果使用十进制字面量,它的工作方式相同

byte enabledByte = enabled ? (byte) 1 : 0; 

请参阅JLS-15.25.2 - 数字条件表达式,其中部分内容如下:

否则,将应用二进制数字提升(§5.6.2)到操作数类型,并且条件表达式的类型是第二个和第三个操作数的提升类型。


0

关于从 intbyte 的缩小转换规则在语言规范中有明确说明,详见赋值上下文章节(重点在常量表达式上):

此外,如果表达式是类型为 byteshortcharint 的常量表达式(§15.28):

  • 如果变量的类型是 byteshortchar,并且常量表达式的值可以表示为变量的类型,则可以使用缩小原始类型转换。

...

如果表达式的类型不能通过赋值上下文中允许的转换转换为变量的类型,则会发生编译时错误。

三元条件表达式enabled ? 0x01 : 0x00不是一个常量表达式,与整数字面值不同。因此,它不能使用缩小转换进行隐式转换。

请注意,您可以通过将条件表达式的操作数之一强制转换来解决错误:

byte enabledByte = enabled ? (byte) 0x01 : 0x00;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接