我很想知道使用二进制文字的按位比较实际发生了什么。我刚刚遇到了以下事情:
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
s(,只表示0b00000000 00000000 00000000 11111111
,而b2
是一个表示值-1
的字节。在转换为int
的过程中,该值被保留,因此b2
被转换为表示相同数字(-1
(:0b11111111 11111111 11111111 11111111
的32位整数。
然后,xor
计算结果为 0b11111111 11111111 11111111 00000000
这是 -256
的 32 位二进制表示形式。
如果使用(byte)0b11111111
执行xor
比较,则二进制文本也将被视为一个字节,因此等效地转换为表示-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
。
进一步阅读为什么可以在这里完成:
- 类型和 Java 虚拟机
- java 中的按位运算符仅适用于整数和长整型?
当你使用b1 ^ 0b11111111
时,你实际上在字节到整数之间做了xor
byte
是 8 位变量,而int
是 32 位数字。所以,你所做的是: b1 ^ 0b(00000000 00000000 00000000 11111111)
因此,当您在byte
之间使用xor
时(在它之前有额外的 1 以将其与 int. 1 一起使用,因为它是一个否定数字。如果它是正数,则为 0s(,int
结果将是一个整数,在您的情况下为 -256。
当您将整数转换为byte
您在两个字节之间使用xor
时,结果将是一个字节。