Reputation: 21019
Bytes in Java are signed by default. I see on other posts that a workaround to have unsigned bytes is something similar to that: int num = (int) bite & 0xFF
Could someone please explain to me why this works and converts a signed byte to an unsigned byte and then its respective integer? ANDing
a byte with 11111111 results in the same byte - right?
Upvotes: 17
Views: 43059
Reputation: 121
In Java 8 such method appeared in Byte class:
/**
* Converts the argument to an {@code int} by an unsigned
* conversion. In an unsigned conversion to an {@code int}, the
* high-order 24 bits of the {@code int} are zero and the
* low-order 8 bits are equal to the bits of the {@code byte} argument.
*
* Consequently, zero and positive {@code byte} values are mapped
* to a numerically equal {@code int} value and negative {@code
* byte} values are mapped to an {@code int} value equal to the
* input plus 2<sup>8</sup>.
*
* @param x the value to convert to an unsigned {@code int}
* @return the argument converted to {@code int} by an unsigned
* conversion
* @since 1.8
*/
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
Upvotes: 12
Reputation: 4645
As you see the result is an int
not a byte
How it works, say we have a byte b = -128;
, this is represented as 1000 0000
, so what happens when you execute your line? Let's use a temp int for this, say:
int i1 = (int)b;
i1 is now -128 and this is actually represented in binary like this:
1111 1111 1111 1111 1111 1111 1000 0000
So what does i1 & 0xFF
look like in binary?
1111 1111 1111 1111 1111 1111 1000 0000
&
0000 0000 0000 0000 0000 0000 1111 1111
which results in
0000 0000 0000 0000 0000 0000 1000 0000
and this is exactly 128, meaning your signed value converted to unsigned.
Edit
Convertint byte -128 .. 127
into 0 .. 255
int unsignedByte = 128 + yourByte;
You cannot represent the values 128 to 255 by using a byte, you must use something else, like an int or a smallint.
Upvotes: 3
Reputation: 346240
ANDing a byte with 11111111 results in the same byte - right?
Except you're ANDing with 00000000000000000000000011111111, because 0xFF is an int
literal - there are no byte
literals in Java. So what happens is that the byte
is promoted to int
(the typecast is unnecessary), has its sign extended (i.e. keeps the possibly negative value of the byte
, but then the sign extension is reverted by ANDing it with all those zeroes. The result is an int
that has as its least significant bits exactly the former byte
and thus the value the byte
would have had were it unsigned.
Upvotes: 16
Reputation: 87773
Yes, but this way you can be sure you will never get a number >255 or <0.
If the first bit is 1, the number is negative. If you convert byte to int, if it is negative it will be pre-pended with 1 bytes and if positive, with 0 bytes. Running the and routine will drop all the bytes left of the first 8. This in effect adds 256 to negative bytes.
Upvotes: 0
Reputation: 128749
A typecast has a higher precedence than the &
operator. Therefore you're first casting to an int, then ANDing in order to mask out all the high-order bits that are set, including the "sign bit" of the two's complement notation which java uses, leaving you with just the positive value of the original byte. E.g.:
let byte x = 11111111 = -1
then (int) x = 11111111 11111111 11111111 11111111
and x & 0xFF = 00000000 00000000 00000000 11111111 = 255
and you've effectively removed the sign from the original byte.
Upvotes: 27