Widening conversions (eg. byte
to int
) are generally accepted implicitly by the Java compiler, as there's no loss of information (the range of int
is greater than that of byte
).
Narrowing conversions (eg. long
to int
, as in your case) can cause a loss of information, so are generally required to be explicitly casted.
See this similar question, and this. A relevant piece of the Java Language Specification:
Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable.
...
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.
(emphasis mine)
Some confusion stems from the fact that we're dealing in particular with constant expressions, as we're using numeric literals. The above spec also needs some careful reading.
To clear some things up and directly answer some of the OP's queries:
Why implicit narrowing is supported for one type of narrowing and not the other?
Ie. why does byte b1 = 127
work implicitly, while int i5 = 100L
not?
byte b1 = 127
performs an implicit conversion as (cf. the bold text in the above quote), "the value of the constant expression is representable in the type byte". That is, 127
is representable by a byte
, so the conversion is implicit. If you try byte b1 = 128
, you'll get an error about incompatible types, as 128
isn't representable by byte
. The only reason we're allowed an implicit cast here at all is because we're using a constant expression.
We don't get an implicit conversion in int i5 = 100L
(even though 100 is in the range of int
) as that's simply not listed in the allowed implicit conversions (the variable's type, int
, is not one of byte
, short
, or char
).
We also don't get an implicit conversion in byte a = 0L
, this time as the constant expression is of type long
, not of type byte
, short
, char
, or int
.
How will a normal programmer know which narrowing conversion is allowed implicitly?
The implicit narrowing conversions only occur when you're assigning a constant expression to a variable. In these cases, implicit conversions are good as we don't want to be writing code like byte b = (byte)0
all the time. At the same time, we do want to be warned if we write something like byte b = 128
, as that doesn't have intuitive behaviour.
When we're not assigning constant expressions (so eg. int x = 0; byte b = x;
), we always want to be warned when we're doing a potentially lossy conversion, as they're dangerous - so explicit conversions in this case also make sense.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…