Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is 7 / 3 not always an int? Why can it be assigned into byte or short while x/3 cannot? [duplicate]

Tags:

java

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.

like image 285
Code Complete Avatar asked Dec 18 '22 22:12

Code Complete


1 Answers

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.

like image 147
Jacob G. Avatar answered May 10 '23 19:05

Jacob G.