I'm trying to bitshift right in order to isolate certain bits from a byte so I wanted an unsigned shift, the "new" bits should be zeros by my understanding. However, I've found that >>> has no difference to >> in my tests. -128 >> 4 = -8 as expected, but -128 >>> 4 should be 8 but I still get -8.
byte data = (byte)-128;
System.out.println((byte)(data >>> 4));
System.out.println((byte)(data >> 4));
Thanks for the help.
The unsigned right-shift operator is indeed doing an unsigned right-shift in this code; it's just hidden because of implicit cast from byte
to int
. Says the Java Language Specification (§15.19):
The operators
<<
(left shift),>>
(signed right shift), and>>>
(unsigned right shift) are called the shift operators. The left-hand operand of a shift operator is the value to be shifted; the right-hand operand specifies the shift distance. [...] Unary numeric promotion (§5.6.1) is performed on each operand separately.
Unary numeric promotion means (§5.6.1):
[...] if the operand is of compile-time type
byte
,short
, orchar
, it is promoted to a value of typeint
by a widening primitive conversion (§5.1.2).
So your code is evaluated as follows:
- The
byte
value-128
which is the left operand of>>>
is promoted to theint
value-128
, which is0b11111111111111111111111110000000
in binary. - The unsigned right-shift is done on this
int
value, with the result268435448
which in binary is0b00001111111111111111111111111000
. Note that the four left-most bits are zero, as you would expect from an unsigned right-shift. - This result is then explicitly casted to
(byte)
, giving the result-8
.
Using the REPL:
> byte b = -128;
> int shifted = b >>> 4;
> shifted
268435448
> (byte) shifted
-8
For the behaviour you want, you can use & 0xFF
to do an "unsigned" conversion from byte
to int
:
> ((b & 0xFF) >>> 4)
8