Java:为什么二进制OR不按预期工作(参见下面的代码)?

我不明白以下代码的输出:

public static void main(String[] args) { int i1, i2, i3, i4; byte b; i1 = 128; b = (byte) i1; i2 = (int) b; i3 = 0 | b; i4 = 1 << 7; System.out.format("i1: %db: %d i2: %d i3: %d i4: %d\n", i1, b, i2, i3, i4); } 

输出:

 i1: 128 b: -128 i2: -128 i3: -128 i4: 128 

因为byte是一个8位二进制补码有符号整数,所以在最高有效位中带有1的二进制表示被解释为负值,这就是为什么b变为-128 ,我完全没问题。 我也明白,在投射时保持解释一致可能是个好主意,就像i2 。 但是i3i4不应该有相同的位模式,因此映射到相同的int值?

符号扩展是使i2i3负的原因。

在表达式(0 | b)b被提升为int,并且作为此促销的一部分发生符号扩展。

在分配给i4的表达式中没有发生这种情况。 常量17已经是整数,因此不涉及符号扩展。

在这一行:

 i3 = 0 | b; 

由于|,“b”变量自动提升为带有符号扩展名的int类型 运算符,因此变为(int)-128 ,即0xffffff80

当“或”ed为零时,它仍然是相同的值,即-128

不, i4不是字节值,它是一个int 。 这意味着它的符号位是第31位,而不是第7位。

更新i3也是一个int ,但它是通过扩展一个byte来初始化的,所以它保持符号不受byte值的影响。

i2 = (int) b;

i3 = 0 | b;

i3语句相当于:

i3 = 0 | ((int) b) = 0 | i2 i3 = 0 | ((int) b) = 0 | i2很自然地它将具有与i2相同的值

这很简单。 i3 = 0 | b; 得到像byte一样的评估,然后它被转换为int 。 而i4 = 1 << 7; 将值评估为int并将其分配给int 。 所以在第一种情况下,我们从byte获得10000000bint ,这将给出-128 。 在第二个我们只是将这个值赋给int而不使用强制转换,这给了我们128

如果要在字节中获取位模式的无符号值:

 b & 0xff 

另见这个旧答案 。

 i3 = 0 | b; 

我猜0 | b part被评估为一个字节,然后将结果转换为int,而in

 i4 = 1 << 7; 

1 << 7部分已经是一个int。

以上猜测已经在评论中指出是错误的!

正确的版本是:在顶部表达式中,在OR操作之前,b已经转换为带符号扩展名的int。