考虑
int a = 20;
a = a + (a = 5); // a == 25, why not 10?
括号不要胜过所有优先规则吗?在评估某些表达式之前,RHS上的一些变量是否已预先填充?
答案 0 :(得分:5)
因为在您拥有的示例中首先加载a
,然后然后评估括号中的位。如果您颠倒了订单:
int a = 20;
a = (a = 5) + a;
System.out.println(a);
10
...你确实得到10.表达式从左到右进行评估。
考虑一下:
f() + g()
f
将在g
之前调用。想象一下,在
f() + (g())
要在g
之前调用f
。
JLS §15.7.1详细介绍了这一点(感谢@paisanco在评论中提出这一点。)
答案 1 :(得分:4)
来自JLS
Java编程语言保证了操作数 运算符似乎在特定的评估顺序中进行评估, 即,从左到右。
和
二元运算符的左侧操作数似乎是完全的 在评估右手操作数的任何部分之前进行评估。
在括号中包装表达式只是为了帮助分组(和关联性),它不会强迫它的评估发生在它左边的任何东西之前。
答案 2 :(得分:2)
生成的字节码:
BIPUSH 20
ISTORE 1
ILOAD 1
ICONST_5
DUP
ISTORE 1
IADD
ISTORE 1
RETURN
LOCALVARIABLE a I
首先,为第一个变量(a)指定20:
BIPUSH 20
ISTORE 1
然后,将第一个变量的内容加载到堆栈中(20放在堆栈上):
ILOAD 1
然后,你推动常数' 5'到堆栈两次(20 5 5):
ICONST_5
DUP
然后,将堆栈顶部存储到第一个变量(a):
ISTORE 1
a现在是5,堆栈现在是(20 5)。我们添加两个操作数并将它们的和加到第一个变量(a):
IADD
ISTORE 1
因此,a现在是20 + 5 = 25.我们结束:
RETURN