为什么7/3不总是int?为什么它可以分配到字节或短,而x/3不能?

Cod*_*ete 4 java

我认为任何算术表达式的结果至少是一个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?
Run Code Online (Sandbox Code Playgroud)

和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
}
Run Code Online (Sandbox Code Playgroud)

PS问题是不同的,因为我知道7/3会因整数除法而给出2(舍入为零),但它应该是一个int,而不是字节或短.

Jac*_* G. 11

byte f1() {
    return 7 / 3;    // Why is it allowed?  Why isn't 7 / 3 an int ?
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,结果在字节范围(-128to 127)内,并且编译器足够聪明,可以意识到它可以隐式地将int结果转换byte为由方法返回的结果.

JLS 14.17:当一个return带有Expression的语句出现在方法声明中时,Expression必须可赋值(第5.2节)到声明的方法返回类型,否则会发生编译时错误.

JLS 5.2:如果表达式是一个常量表达式(§15.28类型的)byte,short,char,或int:

  • 如果变量是type byte,shortchar,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示.

byte f2(int x) {
    return x / 3;   // c.ERR - type mismatch
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,因为它x是一个int,它可以是一个大数,当除以时3,将不在范围byte内,因此编译器知道它不应该尝试隐式地将它转换为a byte,因为结果可能不是期望.

JLS 14.17:当一个return带有Expression的语句出现在方法声明中时,Expression必须可赋值(第5.2节)到声明的方法返回类型,否则会发生编译时错误.


byte f3(byte x) {
    return x / 3;   // c.ERR - type mismatch
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,当使用a byte和a进行算术运算时int,byte会自动将其上传到int(如JLS中所定义).这导致与第二个相同的情况; 即使我们知道结果必须在byte范围内,编译器也不会,因为除以3可以改为乘以9999....

JLS 15.17:对操作数执行二进制数字提升(第5.6.2节).

JLS 5.6.2:应用扩展原语转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:

  • 如果任一操作数是类型double,则另一个操作数转换为double.

  • 否则,如果任一操作数是类型float,则另一个操作数转换为float.

  • 否则,如果任一操作数是类型long,则另一个操作数转换为long.

  • 否则,两个操作数都将转换为类型int.

  • 说得通.... (2认同)