1 + 2
是一个常量表达式,而a + b
不是。
它对评估它们很重要。
第一个将在编译时完成,第二个在运行时完成。
的JLS 8状态:
15.28。常量表达式
常量表达式是一个表达式表示原始 类型或字符串的一个值,该值不会突然完成并仅使用 由下列:
原始类型和文字的
........................
这里:
short c = 1 + 2;
1 + 2
是由两个int
文字和一个加法运算符组成。
所以它被认为是一个常数表达式。
在编译时评估常量表达式。
所以short c
作为3
这里评估是一个示例类:
package stackoverflow;
public class EvaluationClass {
public void foo(){
short c = 1 + 2;
}
}
下面是反汇编代码:
Compiled from "EvaluationClass.java"
public class stackoverflow.EvaluationClass {
public stackoverflow.EvaluationClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()
4: return
public void foo();
Code:
0: iconst_3
1: istore_1
2: return
}
我们可以看到,装载3
int
到0: iconst_3
指令堆栈。
鉴于此:
short a = 1;
short b = 2;
short c = a + b;
a + b
仅在运行时评价为a
和b
不是恒定值。
它们的值可能在任何时候都会改变。
请注意,如果a
和b
有效变异,则编译器不会试图通过阅读每个语句来猜测。
它认为它只能在运行时评估a + b
。
现在在这种情况下,为什么a + b
不会产生short
而是int
?
由于JLS 8规定:
4.2.2。整数运算
如果比的变速操作者以外的整数操作者有long类型中的至少一个 操作数,则该操作被执行使用64位 精度,数值运算符的结果是类型长的。 如果另一个操作数不长,则首先扩展(§5.1.5),以便通过数字提升键入 (§5.6)。
否则,操作是使用32位精度进行的,并且 数值运算符的结果是int类型的结果。如果任一操作数 不是int,则首先将其扩展为通过数字提升来键入int。
作为一个侧面说明,如果更改代码,使a
和b
constants
:
final short a = 1;
final short b = 2;
short c = a + b;
这将现编译罚款a + b
将作为一个常量表达式进行评估(3
) 。
由于两个操作数都是编译时间常数,因此可以在编译时计算“1 + 2”。换言之,'short c = 1 + 2;'将编译为'short c = 3;'。如果结果超出“短”范围,您仍然会出错。 – Pshemo
@Pshemo那么这意味着一个'int'会被明确地降低为'short'?因为1 + 2或者被解析为'short'仍然会被评估为'int',否? – dosdebug
@dosdebug不,这里没有添加。它的编译方式与'short c = 3'相同;' – Neo