1. 程式人生 > >a = a++與 a = ++a詳解

a = a++與 a = ++a詳解

以前對a++與++a的理解僅限於:
a = a++先賦值後計算,a = ++a先計算後賦值。
單從應用的角度來講,這麼簡單理解是沒有問題的。

這篇部落格用來深入理解並測試二者真正的區別。一句話說到前頭,
a = a++與a = ++a均為先計算後賦值,不同的是:
a = a++中變數先壓棧,後計算,最後棧頂元素彈出賦值於a;
a = ++a中變數先計算,後壓棧,最後棧頂元素彈出賦值於a。

詳解如下:
先了解一些反編譯的基礎知識:
JVM指令詳解,可以看這兩篇部落格:部落格1 部落格2
在這裡我們只需要瞭解幾個指令就行:

助記符         說明
iconst_1 : 將int
型(1)推送至棧頂 istore_1 : 將棧頂int型數值存入第二個本地變數。(main方法中,第一個本地變數是String[] args,第二個開始才是自己定義的變數) iload_1 : 將int型陣列指定索引的值推送至棧頂(在下面的測試程式碼中,指的就是變數a,即把a的值壓入棧頂) iinc 1, 1: 該指令第一引數為本地變數的編號,第二個引數為自增減的數量。(這裡的意思就是將本地第二個變數(int型)的值+1

a = a++
測試程式碼:

public class test{
    public static void main(String[] args) {
        int
a=1; a = a++; System.out.println(a); } }

反編譯結果:
a = a++
反編譯結果解釋:

a = a++;
Code:
   0: iconst_1      棧頂:1  a: 0
   1: istore_1      棧頂:已彈出該元素  a: 1
   2: iload_1       棧頂:1  a: 1
   3: iinc          1, 1                棧頂:1  a: 2
   6: istore_1      棧頂:已彈出該元素  a: 1
   7: getstatic     #2
// Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_1 棧頂:1 11: invokevirtual #3 取棧頂元素輸出1 // Method java/io/PrintStream.println:(I)V 14: return

a = ++a
測試程式碼:

public class test{
    public static void main(String[] args) {
        int a=1;
        a = ++a;
        System.out.println(a);
    }
}

反編譯結果:
a = ++a
反編譯結果解釋:

a = ++a;
Code:
     0: iconst_1        棧頂:1  a: 0
     1: istore_1        棧頂:已彈出該元素  a: 1
     2: iinc          1, 1      棧頂:已彈出該元素  a: 2
     5: iload_1         棧頂:2  a: 2
     6: istore_1        棧頂:已彈出該元素  a: 2
     7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    10: iload_1         棧頂:2
    11: invokevirtual #3        取棧頂元素輸出2          // Method java/io/PrintStream.println:(I)V
    14: return