I attempted to duplicate this with a wider group of assignment contexts:
final byte b = 12;
Byte b2 = b;
Character c = b; // Only an error if b isn't final
char c2 = b; // Only an error if b isn't final
Short s = b; // Only an error if b isn't final
short s2 = b;
Integer i = b; // Error, as indicated in the question
int i2 = b;
Long l = b; // Also an error
long l2 = b;
Float f = b; // Also an error
float f2 = b;
Double d = b; // Also an error
double d2 = b;
Assigning not just to a Integer
, but also to a Float
, a Long
or a Double
is also an error.
Interestingly, if the original declaration of b
was NOT final
, then assigning to a Character
, a char
, or a Short
fails also.
Section 5.2 of the JLS sheds a little light on the subject of assignment contexts and their allowed conversions.
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
an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.
This covers all of the conversions to wider primitive variables, which are always allowed, whether b
is final
or not. (That holds unless b
is negative, in which case the assignment to an unsigned char
(or Character
) would fail.) Continuing:
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.
Because b
is final
, the expression b
is a constant expression, allowing it to be narrowed from the int
constant expression 12
to byte
, char
, or short
and then boxed to Byte
, Character
, or Short
, but strangely, not to Integer
or anything "above". The only possible explanation I can think of is that constant expressions that are subject to a primitive narrowing conversion aren't specifically allowed to be converted to Integer
, Long
, Float
, or Double
.
If b
isn't final
, then the narrowing followed by boxing isn't allowed, and a non-constant expression can't be promoted from byte
to char
either.
Short
is allowed, butInteger
isn't so I retracted the closevote. Nevertheless very related: #7014671 – BeauteousCharacter c = b
compiles just fine too. Butchar
s are unsigned! So what happens when you changeb
to-12
? It then fails to compile! – Guesthouse