增量后为什么在这里忽略这个Java运算符优先级?
下面的代码打印出“3”,而不是预期的“4”
public class Foo2 {
public static void main(String[] args) {
int a=1, b=2;
a = b + a++;
System.out.println(a);
}
}
我知道怎么做。后缀增量发生在加载“a”的值之后。(见下文)
我不太明白的是为什么。postfix++的运算符优先级高于+,所以它不应该先执行吗
% javap -c Foo2
Compiled from "Foo2.java"
public class Foo2 extends java.lang.Object{
public Foo2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_2
5: iload_1
6: iinc 1, 1
9: iadd
10: istore_1
11: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
14: iload_1
15: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
18: return
# 1 楼答案
后缀
++
增加变量的值,返回在增加之前的值。因此,示例中operator++
的返回值将是1
,当然1 + 2
将给出3
,然后将其分配给a
。到赋值时,++
已经将a
的值增加到2
(因为优先级),所以=
覆盖增加的值# 2 楼答案
这里不忽略运算符优先级
关于
a++
唯一稍微令人困惑的是,后缀++
操作符有两种不同的效果:因此,如果
a
在这一行前面有1,而b
在这一行前面有2:然后执行以下步骤:
b
b
的值为2,所以记住值2a++
a++
的值为1,所以记住值1a
中的值增加1,这样它现在就可以保存值2a
如您所见,代码有效地为
a
分配了两个值:a++
的计算过程中,2被分配给a
a
因为第二个赋值发生在第一个赋值之后,所以您只会看到第二个赋值的效果,并且始终会观察到
a
在该行后面有值3编辑:我将尝试提供反编译代码的解释。这可能有点难以理解,除非您知道JVM在内部是如何工作的(即,您知道JVM是如何基于堆栈的VM,以及这意味着什么):
第0-3行只是实现
第4-10行执行
我漏掉了其他几行,因为那里再也没有什么有趣的事情发生了
作为一个有趣的旁注:显而易见,这段代码根本没有经过优化。原因是优化是Java世界中运行时环境(即JVM)的任务,而不是编译器的任务(例如^{)
# 3 楼答案
后递增/递减运算符(a++)返回递增之前的值。预增量/减量(++a)返回增量后的值
# 4 楼答案
postfix++操作符的意思是:
在任何等式中使用变量的原始值,然后增加变量
# 5 楼答案
这不是优先级问题,而是运算符的定义问题根据定义后缀运算符在封闭表达式中使用变量后执行
# 6 楼答案
我对这个操作符优先级定义(定义为here)也有同样的问题,我认为上面的回答都不能准确地解释和澄清这个定义中的悖论。 这就是我认为后缀运算符比其他运算符(在本例中是二进制加号运算符)优先级更高的意思
考虑下面的代码片段:
如您所见,java编译器会将具有两个可能求值的单个表达式
z = x+++y;
求值为z = x++ + y;
。这意味着,从三个加号中,编译器假定前两个是后缀运算符,第三个是二进制加号运算符 这实际上是后缀运算符的优先级高于其他运算符的结果第二个代码片段通过将表达式写为
z = x + ++y;
来显示输出的差异,该表达式明确指定哪个加号是二进制运算符