All basic integer types in Java are signed. To be exact, byte
, short
, int
and long
are signed big endian two complement integers. That means that they run from - 2n-1 to 2n-1 - 1 where n is the number of bits - 8 for a byte (Byte.SIZE
in Java), and therefore the range is from -128 to 127.
The number you are using is always an integer; number literals always are. However, the integer is actually the value 0x000000FF
in hexadecimals. That cannot be stored as it is higher than 127. You can however do an explicit conversion; your value does consist of 8 bits after all.
byte b = (byte) 0b1111_1111
works because it simply disregards the 24 bits from the left hand side of the value. Now if you print it you will get -1 as value though as 0b1111_1111
represents 1 in 8 bit two complement form.
If you need it to represent the integer value 255 then you need to perform the following little trick:
int i = b & 0xFF;
which will actually do the following:
- First it will convert b to the value
0xFFFFFFFF
as integer using sign extension as all calculations default to integer, and it still thinks that b represents -1 after all.
- Then it performs a bitwise AND with the value
0x000000FF
(which is called a "mask"), resulting of course in the same value 0x000000FF
which represents 255.
If you think this is a nuisance then you are right. Java should have used unsigned bytes, but it decided to use only one particular integer type that is signed. Maybe a bit overzealous but still a big improvement over e.g. C where you have way too many integer formats, and each of them may be represented differently on various machines.