byte f1() {
return 7 / 3; // Why is it allowed? Why isn't 7 / 3 an int ?
}
In the above snippet, the result is within byte range (-128
to 127
), and the compiler is smart enough to realize that it can implicitly cast the int
result to a byte
to be returned by your method.
JLS 14.17: When a return
statement with an Expression appears in a method declaration, the Expression must be assignable (§5.2) to the declared return type of the method, or a compile-time error occurs.
JLS 5.2: 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 variable is of type
byte
, short
, or char
, and the value of the constant expression is representable in the type of the variable.
byte f2(int x) {
return x / 3; // c.ERR - type mismatch
}
In the above snippet, because x
is an int
, it can be a large number that, when divided by 3
, will not be within byte
range, so the compiler knows that it shouldn't attempt to implicitly cast it to a byte
, as that result may not be desired.
JLS 14.17: When a return
statement with an Expression appears in a method declaration, the Expression must be assignable (§5.2) to the declared return type of the method, or a compile-time error occurs.
byte f3(byte x) {
return x / 3; // c.ERR - type mismatch
}
In the above snippet, when doing arithmetic with a byte
and an int
, the byte
will be automatically upcasted to an int
(as defined in the JLS). This results in the same scenario as number two; even though we know that the result must be within byte
range, the compiler doesn't, because dividing by 3
could be changed to being multiplied by 9999...
.
JLS 15.17: Binary numeric promotion is performed on the operands (§5.6.2).
JLS 5.6.2: Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double
, the other is converted to double
.
Otherwise, if either operand is of type float
, the other is converted to float
.
Otherwise, if either operand is of type long
, the other is converted to long
.
Otherwise, both operands are converted to type int
.