I'm preparing for Java 7 certification and have the following question.
Byte b = 10
compiles ok. Looks like the compiler is narrowing int 10 to byte 10 and then boxing it. How come Byte b = new Byte(10)
won't compile? Why can't the compiler narrow int 10 to byte 10 like it did in the first case?
Also how come Long l = new Long(10)
compiles ok but Long l = 10
fails?
I'm not clear about how this works. Can somebody provide an clear explanation?
A widening conversion changes a value to a data type that can allow for any possible value of the original data. Widening conversions preserve the source value but can change its representation. This occurs if you convert from an integral type to Decimal , or from Char to String .
Narrowing conversion is needed when you convert from a larger size type to a smaller size. This is for incompatible data types, wherein automatic conversions cannot be done. Let us see an example wherein we are converting long to integer using Narrowing Conversion.
In Java, there are two types of casting: Widening Casting (automatically) - converting a smaller type to a larger type size. byte -> short -> char -> int -> long -> float -> double. Narrowing Casting (manually) - converting a larger type to a smaller size type.
A "widening" conversion or typecast is a cast from one data type to another data type, where the "destination" data type has a larger range compare to the "source" data type. For example: int to long. float to double.
Section 5.2 of the JLS covers the types of conversions that are allowed in assignment contexts.
Assignment contexts allow the use of one of the following:
an identity conversion (§5.1.1)
a widening primitive conversion (§5.1.2)
a widening reference conversion (§5.1.5)
a boxing conversion (§5.1.7) optionally followed by a widening reference conversion
Additionally,
In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:
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.
A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:
Byte and the value of the constant expression is representable in the type byte.
Short and the value of the constant expression is representable in the type short.
Character and the value of the constant expression is representable in the type char.
Byte b = 10
compiles ok because 10
is a constant expression and is representable as a byte
.
Byte b = new Byte(10)
won't compile because 10
is an int
literal, and method invocation conversion won't perform primitive narrowing conversions. To get this call to a Byte
constructor to compile, you can explicitly cast 10
to byte
:
Byte b = new Byte( (byte) 10);
Long l = new Long(10)
compiles because method invocation conversion will perform primitive widening conversions, including from int
to long
.
Long l = 10
won't compile, because Java will not specifically allow a widening conversion followed by a boxing conversion, as I discussed in a recent answer. To get this to compile, you can use a long
literal, so only boxing is necessary.
Long l = 10L;
The basic rules are:
These rules explain why Long l = 10
doesn't work, as well as new Byte(10)
. The first would require the int literal 10 to be widened to a long
and then be boxed, which isn't allowed. (More precisely, it would require a conversion from int
to Long
, which JLS 5.1.7 doesn't define.) The second would require the int literal 10 to be implicitly narrowed to a byte
, which isn't allowed.
But there are exceptions to the rule. Byte b = 10
is explicitly allowed by JLS 5.2:
In addition, if the expression is a constant expression (§15.28) of type
byte
,short
,char
, orint
:
- A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:
Byte
and the value of the constant expression is representable in the typebyte
.
(some irrelevant parts omitted)
Lastly, new Long(10)
works because the int literal 10 can be automatically widened to a long 10L.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With