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
int. Says the Java Language Specification (§15.19):
>>(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
char, it is promoted to a value of type
intby a widening primitive conversion (§5.1.2).
So your code is evaluated as follows:
-128which is the left operand of
>>>is promoted to the
-128, which is
- The unsigned right-shift is done on this
intvalue, with the result
268435448which in binary is
0b00001111111111111111111111111000. 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
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
> ((b & 0xFF) >>> 4) 8
The signed right shift operator ‘>>’ uses the sign bit to fill the trailing positions and the unsigned right shift operator ‘>>’ do not use the sign bit to fill the trailing positions. It always fills the trailing positions by 0s