Reputation: 3230
Why will java compiler not let me put 0xff
into a byte
, 0xff
is 8 bits long which is just the size of byte
datatype.
Can someone explain why 1 works and why 2 does not ?
class a
{
public static void main(String[] args)
{
// 1 :: results in error
byte a = 0xff;
System.out.printf("%x\n",a);
//2 :: works fine
byte a = (int)0xff
System.out.printf("%x\n",a);
}
}
EDIT I read the answer claiming that 0xff is 255, how so ? Is it not 1111 1111
, What makes 0xff, -128 or 255 or anything for that matter. Why will it not just treat it as 1111 1111
and not the 8 bits of that byte to 1.
Upvotes: 31
Views: 33021
Reputation: 718826
The Java byte
type is an 8 bit signed integral type with values in the range -128
to +127
. The literal 0xff
represents +255
which is outside of that range.
In the first example, you are attempting to assign a value that is out of range to a byte
. That is a compilation error.
In the second example, the (byte)
cast is performing an explicit narrowing conversion, that removes the high order bits of the integer literal ... giving you the value -127
in your byte
variable.
In fact, the situation with the first example is a bit more complicated than that. Consider this:
byte a = 1; // OK
int i = 1;
byte b = i; // Compilation error
byte c = (byte) i; // OK
Under normal circumstances, you cannot assign an int
to a byte
without a cast. However, if the value are assigning is a literal, and the literal value is within the range of the target type, the Java language permits the assignment without a cast. The literal's value is implicitly narrowed from int
to byte
.
This is described in JLS §5.2 which defines the conversions that may be performed in an assignment:
"A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable."
And as you can see, this doesn't just apply to literals. It applies to all (compile-time) constant expressions!
FOLLOW-UP
I read the answer claiming that
0xff
is255
, how so? Is it not1111 1111
, What makes0xff
,-128
or255
or anything for that matter?
The literal 0xff
is an integer literal. It has type int
. The int
value of the literal 0xff
is actually 0000 0000 0000 0000 0000 0000 1111 1111
in binary or +255 in decimal. By contrast, the integer value -128
has the bit pattern 1111 1111 1111 1111 1111 1111 1000 0000
.
Why will it not just treat it as
1111 1111
and not the 8 bits of that byte to 1?
Because 0xff
is an integer literal; i.e. 32 bits. It is not an 8-bit literal, because 8-bit literals do not exist in Java. As JLS §3.10.1 says:
"An integer literal is of type
long
if it is suffixed with an ASCII letterL
orl
(ell); otherwise it is of typeint
(§4.2.1)."
Upvotes: 58
Reputation: 279970
0xff
is a hexadecimal representation of a number. In other words the number is base 16.
f = 15
in hex.
The value is equal to
15 * 16^1 + 15 * 16^0 = 255
This is an integer literal (uses 4 bytes), which exceeds byte
's value range.
Neither of the two examples you've posted will compile as neither fits into byte
's value range of -128 to 127
. You can read about primitive type value ranges here.
This will work
byte a = (byte)0xff;
System.out.println(a);
and print -1
, because a byte narrowing conversion of 255
is -1
.
Upvotes: 16
Reputation: 41281
0xff
is 255. While this does fit into an 8-bit unsigned integer, byte
is signed(-128 to 127). The narrowing will remove the high bits and fit 8 into 8 without regard for sign.
Upvotes: 4
Reputation: 150
First, if I try to run your code, the 2. case doesn't work either. You cast 0xff to the primitive datatype int (which has 32 bit) and want to store it in a 'byte' with only 8bit. Java treats your first case as int too, resulting in the same problem.
Because the java 'byte' type is an 8-bit signed integer value (from -128 to 127), to output / print the byte as hex, you can use Integer.toHexString('the primitive byte' & 0xFF) where ' & 0xFF ' is a bitmask to take into account that Integer uses a 32bit int and byte uses 8bit.
byte myByte = (byte)0xff;
System.out.println(Integer.toHexString(myByte & 0xFF));
This outputs:
ff
Upvotes: 4