以下代码打印出“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
答案 0 :(得分:19)
Postfix ++
增加变量的值,返回增量之前的值。因此,您示例中operator++
的返回值将为1
,当然1 + 2
将提供3
,然后将其分配给a
。到分配时,++
已将a
的值增加到2
(因为优先级),因此=
会覆盖该增量值。
答案 1 :(得分:13)
此处不会忽略运算符优先级。
关于a++
的唯一有点令人困惑的事情是后缀++
运算符有两个不同的效果:
因此,如果a
包含1且b
在此行之前的值为2,则
a = b + a++;
然后发生以下步骤:
b
b
的值为2,因此请记住值2 a++
a++
的值为1,因此请记住值1 a
中的值增加1,因此它现在保持值2 a
如您所见,代码有效地将两个值分配给a
:
a
期间,a++
作为分配的结果,a
由于第二个赋值发生在第一个赋值之后,你只能看到第二个赋值的效果,并且你总是会看到a
在该行之后的值为3。
编辑:我将尝试提供对反编译代码的解释。它可能有点难以理解,除非您知道JVM如何在内部工作(即您知道JVM是如何基于堆栈的VM以及这意味着什么):
// Push the constant 1 on the stack
0: iconst_1
// Pop the topmost value from the stack (1) and store it in the local variable #1 (a.k.a "a")
1: istore_1
// Push the constant 2 on the stack
2: iconst_2
// Pop the topmost value from the stack (2) and store it in the local variable #2 (a.k.a "b")
3: istore_2
// Load the local variable #2 ("b") and push its value (2) on the stack
4: iload_2
// Load the local variable #1 ("a") and push its value (1) on the stack
5: iload_1
// Increment the local variable #1 by 1 (this action does not use the stack!)
6: iinc 1, 1
// Pop the 2 topmost values from the stack (2 and 1), add them and push the result (3) back on the stack
9: iadd
// Pop the topmost value from the stack (3) and store it in local variable #1 ("a")
10: istore_1
第0-3行简单实现
int a=1, b=2;
第4-10行实施
a = b + a++;
我遗漏了其他几行,因为没有任何有趣的事情发生了。
作为一个有趣的旁注:很明显,这段代码根本没有优化。原因是优化是Java世界中运行时环境(即JVM)的任务,而不是编译器(例如javac
)的任务。
答案 2 :(得分:3)
后增量/减量运算符(a ++)返回增量前的值。 preincrement / decrement(++ a)返回增量后的值。
答案 3 :(得分:2)
我对此运算符优先级定义(如定义here)有同样的问题,我认为上述回复都没有完全解释和澄清此定义中的悖论。 这就是我认为postfix运算符对其他运算符(在本例中为binary plus运算符)的更高优先级意味着。
考虑以下代码片段:
int x = 1, y =4 , z;
z = x+++y; // evaluates as: x++ + y
System.out.println("z : " + z); // z: 5
System.out.println("y : " + y); // y: 4
System.out.println("x : " + x); // x: 2
x = 1; y =4 ;
z = x + ++y;
System.out.println("z : " + z); // z: 6
System.out.println("y : " + y); // y: 5
System.out.println("x : " + x); // x: 1
如您所见,具有两个可能评估的单个表达式z = x+++y;
将由java编译器评估为z = x++ + y;
。这意味着从三个加号组合在一起,编译器将前两个作为后缀运算符,第三个作为二进制加运算符。 这实际上是后缀运算符优先于其他运算符的结果。
第二个代码片段通过将表达式写为z = x + ++y;
来显示输出的不同,它明确指定哪个加号是二元运算符。
答案 4 :(得分:1)
这不是优先事项,而是运营商定义的问题。 根据定义后缀运算符在封闭表达式中使用变量后执行。
答案 5 :(得分:0)
postfix ++运算符所说的是:
在任何等式中使用变量的原始值,然后在之后递增变量。
答案 6 :(得分:0)
我从未见过
a = b + a++;
正在使用,它让我觉得编码不好。像我那样使用它也意味着你可以写:
int a++ = 1;
哪个不起作用。
通常你会看到int a = 1;
int b = 2;
a = b + a; // 3
a = 1;
a++;
a = b + a; // 4