代码之家  ›  专栏  ›  技术社区  ›  Aaron Fi

为什么在这里忽略这个Java操作符优先级?

  •  5
  • Aaron Fi  · 技术社区  · 15 年前

    下面的代码打印出“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
    
    7 回复  |  直到 12 年前
        1
  •  20
  •   Pavel Minaev    15 年前

    ++ 返回增量之前的值 operator++ 在你的例子中将是 1 ,当然 1 + 2 3 ,然后将其分配给 a . 到派遣时, ++ 已经增加了的值 A. 2 (因为优先权),所以 = 覆盖递增的值。

        2
  •  13
  •   Andreas dfa    6 年前

    这里不忽略运算符优先级。

    唯一稍微让人困惑的是 a++ 那是后缀吗 ++ 运算符有两种不同的效果:

    1. 它的返回值等于变量的值 增加了

    所以如果 a 有1和 b

    a = b + a++;
    

    然后执行以下步骤:

    • 估计
      • 表情 B
    • 估计
      • a++ 值为1,所以记住值1
      • 增加变量中的值 A. 乘以1,所以它现在保持值2
    • 添加两个表达式的结果(分别为2和1)
    • 为变量赋值3 A.

    如您所见,代码有效地为

    • 2被分配到 A. 在评估 a++
    • 3被分配到 由于这次任务

    A. 在该行之后具有值3。

    编辑:

       // 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;
    

    a=b+a++;
    

    我省略了其他几行,因为那里再也没有什么有趣的事情发生了。

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

        3
  •  3
  •   DivineWolfwood    15 年前

    后递增/递减运算符(a++)返回递增之前的值。预增量/减量(++a)返回增量后的值。

        4
  •  2
  •   Akram    9 年前

    here )我认为以上的回答都不能准确地解释和澄清这个定义中的悖论。

    考虑下面的代码片段:

        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; z = x++ + y; 由java编译器实现。这意味着,从三个加号组合在一起,编译器假定前两个加号是后缀运算符,第三个加号是二进制加号运算符。 这实际上是后缀运算符优先于其他运算符的结果。

    第二个代码片段通过将表达式写为 z = x + ++y; 它明确指定哪个加号是二进制运算符。

        5
  •  1
  •   Coop Coop    15 年前

    这不是优先级问题,而是运算符的定义问题。

        6
  •  0
  •   Joachim Sauer    15 年前

    postfix++操作符的意思是:

    在任何等式中使用变量的原始值,然后增加变量。

        7
  •  0
  •   WonderWorld    11 年前

    我从未见过

     a = b + a++; 
    

    在使用时,我觉得它的编码很糟糕。我想这样使用它也意味着你可以写:

    int a++ = 1;
    

    这不管用。

    通常你会看到

    int a = 1;
    int b = 2;
    a = b + a; // 3
    
    a = 1;
    a++;
    a = b + a; // 4