我很好奇知道使用二进制文字进行按位比较时实际发生的情况。我刚遇到以下事情:
byte b1 = (new Byte("1")).byteValue();
// check the bit representation
System.out.println(String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0'));
// output: 00000001
System.out.println(b1 ^ 0b00000001);
// output: 0
因此,一切都按预期运行,
xor
比较等于0
。但是,当用负数尝试相同时将不起作用:byte b2 = (new Byte("-1")).byteValue();
// check the bit representation
System.out.println(String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0'));
// output: 11111111
System.out.println(b2 ^ 0b11111111);
// output: -256
我本以为最后的
xor
比较也等于0
。但是,只有当我将二进制文字显式转换为byte
时,才是这种情况:byte b2 = (new Byte("-1")).byteValue();
// check the bit representation
System.out.println(String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0'));
// output: 11111111
System.out.println(b2 ^ (byte)0b11111111);
// output: 0
对我来说,在
xor
比较之前,b1
和0b11111111
都具有相同的位表示形式,因此,即使它们被强制转换为int
(或其他),xor
仍应等于0
。您如何得出-256
的结果,它是二进制表示形式的11111111 11111111 11111111 00000000
?为什么我必须对byte
进行显式转换才能获得0
? 最佳答案
没有特定类型转换的二进制文字表示32位整数值,无论有多少位数。例如,0b00000001
是0b00000000 00000000 00000000 00000001
的简写。
Java中的按位比较使用二进制数字提升(请参见Javadocs)。在这种特定情况下,这意味着在执行比较之前,两个操作数都将转换为int
。0b11111111
已经表示一个int
(没有前导0
),仅表示0b00000000 00000000 00000000 11111111
,而b2
是一个字节,表示值-1
。在转换为int
的过程中,将保留该值,因此将b2
强制转换为表示相同数字(-1
):0b11111111 11111111 11111111 11111111
的32位整数。
然后,xor
的计算结果为0b11111111 11111111 11111111 00000000
,这是-256
的32位二进制表示形式。
如果使用xor
执行(byte)0b11111111
比较,则二进制文字也将被视为一个字节,因此等效地转换为表示-1
的32位整数。
重要的是要注意,二进制比较是使用double, float, long
或int
(在Javadocs中指定的)执行的。如果只有其他类型参与比较(例如byte
),它们将被转换为int
。这就是为什么下面的代码会给出编译错误的原因:
byte b1 = (byte)0b00000001;
byte b2 = (byte)0b00000001;
byte b3 = b1 & b2;
>>> error: incompatible types: possible lossy conversion from int to byte
...因为两个
byte
的按位比较结果是int
。在这里可以进一步了解为什么:
Types and the Java Virtual Machine
Bitwise operators in java only for integer and long?