为什么在此忽略此Java运算符优先级?

Aar*_* Fi 5 java post-increment

以下代码打印出"3",而不是"4",如您所料.

public class Foo2 {
    public static void main(String[] args) {
        int a=1, b=2;             
        a = b + a++;
        System.out.println(a);
    } 
}
Run Code Online (Sandbox Code Playgroud)

我明白了.在加载"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
Run Code Online (Sandbox Code Playgroud)

Pav*_*aev 20

Postfix ++递增变量的值,并返回增量前的值.因此,operator++您的示例中的返回值将是1,当然1 + 2将给出3,然后将其分配给a.到赋值时,++已经增加了ato 的值2(因为优先级),所以=覆盖递增的值.


Joa*_*uer 13

此处不会忽略运算符优先级.

唯一有点令人困惑的事情a++是后缀++运算符有两个不同的效果:

  1. 它增加了它应用的变量
  2. 它的返回值等于变量增加之前的值

因此,如果a有1并且b在此行之前具有值2:

a = b + a++;
Run Code Online (Sandbox Code Playgroud)

然后执行以下步骤:

  • 评估 b
    • 表达式b的值为2,所以请记住值2
  • 评估 a++
    • 表达式a++的值为1,因此请记住值1
    • 将变量中的值递增a1,因此它现在保持值2
  • 添加两个表达式的结果(分别为2和1)
  • 2 + 1 = 3
  • 为变量赋值3 a

如您所见,代码有效地将两个值分配给a:

  • a在评估期间分配2a++
  • a作为分配的结果,3被分配

由于第二个赋值发生在第一个赋值之后,因此您只能看到第二个赋值的效果,并且您将始终观察到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
Run Code Online (Sandbox Code Playgroud)

第0-4行简单地实现

int a=1, b=2;
Run Code Online (Sandbox Code Playgroud)

第4-10行实现

a = b + a++;
Run Code Online (Sandbox Code Playgroud)

我已经遗漏了其他几行,因为没有任何有趣的事情发生了.

作为一个有趣的旁注:很明显,这段代码根本没有优化.原因是优化是Java世界中运行时环境(即JVM)的任务,而不是编译器(javac例如).