I'm curious to know what actually happens on a bitwise comparison using binary literals. I just came across the following thing:
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
So everything behaves as expected, the xor
comparison equals 0
. However when trying the same with a negative number it won't work:
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
I would have expected that the last xor
comparison also equals 0
. However this is only the case if I do an explicit cast of the binary literal to 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
For me it looks like that before the xor
comparison both b1
and 0b11111111
have the same bit representation so even if they get casted to int
(or something else) the xor
should still equal 0
. How do you come to the result of -256
which is 11111111 11111111 11111111 00000000
in binary representation? Why do I have to do an explicit cast to byte
in order to obtain 0
?
Binary literals without a specific cast represent 32-bit integer values, no matter how many digits there are. For example 0b00000001
is a shorthand for 0b00000000 00000000 00000000 00000001
.
Bitwise comparisons in Java use binary numeric promotion (see the Javadocs). In this specific case it means that both operands get converted to int
before the comparison is performed.
0b11111111
is already representing an int
(without leading 0
s) and just represents 0b00000000 00000000 00000000 11111111
, while b2
is a byte representing the value -1
. During the conversion to int
the value is preserved and thus b2
is cast to a 32-bit integer representing the same number (-1
): 0b11111111 11111111 11111111 11111111
.
The xor
then evaluates to 0b11111111 11111111 11111111 00000000
which is the 32-bit binary representation of -256
.
In case the xor
comparison is performed using (byte)0b11111111
the binary literal will also be treated as a byte and thus equivalently cast to a 32-bit integer representing -1
.
It is important to note that binary comparisons are performed with either double, float, long
or int
(as specified in the Javadocs). If there are only other types participating in the comparison (as for example byte
) they will be converted to int
. That is why the following piece of code will give a compilation error:
byte b1 = (byte)0b00000001;
byte b2 = (byte)0b00000001;
byte b3 = b1 & b2;
>>> error: incompatible types: possible lossy conversion from int to byte
... because the result of a bitwise comparison of two byte
is an int
.
Further reading about the why can be done here: