我认为任何算术表达式的结果至少是一个 int。 7/3 是一个表达式 - 它有一个运算符(除法)。
但为什么编译正常?
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?
f1() 编译正常吗?
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
}
附言问题是不同的,因为我知道 7/3 作为整数除法(向零舍入)的结果会得到 2,但它应该是一个 int,而不是 byte 或 short。
byte f1() {
return 7 / 3; // Why is it allowed? Why isn't 7 / 3 an int ?
}
在上面的代码片段中,结果在字节范围内(-128
到 127
),编译器足够聪明,可以意识到它可以隐式转换 int
结果到 byte
将由您的方法返回。
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
}
在上面的代码片段中,因为 x
是一个 int
,它可以是一个很大的数字,当除以 3
时,将 < strong>不在 byte
范围内,因此编译器知道它不应该尝试将其隐式转换为 byte
,因为结果可能不是想要的。
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
}
在上面的代码片段中,当使用 byte
和 int
进行算术运算时,byte
将自动向上转换为 int
(在 JLS 中定义)。这导致与第二个相同的场景;尽管我们知道结果必须在 byte
范围内,但编译器却不知道,因为除以 3
可以更改为乘以 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
.