I thought that the result of any arithmetic expression is at least an int. 7 / 3 is an expression - it has an operator (division).
But why does this compile fine?
byte b1 = 7 / 3; // 7/3 is not a literal?
short b2 = 7 / 3; // 7/3 is not a literal?
char b3 = 7 / 3; // 7/3 is not a literal?
And f1() compile fine?
byte f1() {
return 7 / 3; // Why is it allowed? Why isn't 7 / 3 an int ?
}
byte f2(int x) {
return x / 3; // c.ERR - type mismatch
}
byte f3(byte x) {
return x / 3; // c.ERR - type mismatch
}
P.S. The question is different, because I know that 7 / 3 would give 2 as a result of integer division (rounding towards zero), but it shall be an int, not byte or short.
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
, orint
:
- A narrowing primitive conversion may be used if the variable is of type
byte
,short
, orchar
, 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 todouble
.Otherwise, if either operand is of type
float
, the other is converted tofloat
.Otherwise, if either operand is of type
long
, the other is converted tolong
.Otherwise, both operands are converted to type
int
.
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