Java j = j++ 与 j = ++j 反编译分析

最近刷Java面试题,遇到这样一题:

public class Test {
    public static void main(String[] args) {
        int j = 0;
        for(int i = 0; i < 100; i++) {
            j = j++;
        }
        System.out.println(j);
    }
}

最后输出的答案为  0。那本书上给的解释是:Java用了中间变量缓存机制,所以,j = j++可换成下面的写法:

temp = j;
j = j + 1;
j = temp;

理解不了这是什么意思。

于是我写了一个测试用例:

public class Jplusplus {
    public static void main(String[] args) {
        int j = 0;
        j = j++;
        j = ++j;
    }
}

先使用 javac Jplusplus.java 编译成 Jplusplus.class字节码文件。

然后再使用 javap -c Jplusplus > Jpp.txt  看看底层到底是怎样执行的,Jpp.txt 里面的内容如下:

Compiled from "Jplusplus.java"
public class Jplusplus {
  public Jplusplus();
    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_0
       1: istore_1
       2: iload_1
       3: iinc          1, 1
       6: istore_1
       7: iinc          1, 1
      10: iload_1
      11: istore_1
      12: return
}

iconst_0 : 将int型0推送至操作数栈顶。

istore_1 : 将操作数栈顶int型数值存入第二个本地变量(j)。(完成了 int j = 0 操作)

iload_1 : 将第二个int型本地变量(j)推送至操作数栈顶。(此时j为0,也就是将0入栈)

iinc  1, 1 : 将第二个int型本地变量(第一个操作数1,也就是j)加1(第二个操作数)。(注意,执行完后j为1了,但是操作数栈顶还是0,这条操作码不改变操作数栈)

istore_1 :将操作数栈顶int型数值存入第二个本地变量(j)。(此时操作数栈顶为0,执行完这条语句后j又变成0了,这也就解释了j=j++执行后为0了)。

下面是 j = ++j。

iinc  1, 1  将第二个int型本地变量(第一个操作数1,也就是j)加1(第二个操作数)。(注意,上面操作码执行完后,j还是0,因此此时j又变成1)

iload_1  :将第二个int型本地变量(j此时是1)推送至操作数栈顶。

istore_1 :将操作数栈顶int型数值(为1)存入第二个本地变量(j).执行完后j为1。

这下就通了!

另一种解释:代码如下

public class Jplusplus {
    public static void main(String[] arg) {
        int j = 0;
        j = j++;
        System.out.println(j);
    }
}

反编译后的代码:

public class Jplusplus {
    public Jplusplus() {
    }

    public static void main(String[] arg) {
        int j = 0;
        byte var10000 = j;
        int var2 = j + 1;
        j = var10000;
        System.out.println(j);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_22158743/article/details/88017927
J
3 J