1. 程式人生 > >通過javap來看看前自增和後自增

通過javap來看看前自增和後自增

今天因為一個偶然的原因,想要認認真真的去驗證一下前自增和後自增到底的本質區別,因為,從一開始我們學習程式語言,學習前自增和後自增,我們的老師就告訴我們,記住它們的區別,前自增是先使用變數的值,再對變數進行+1,後自增是先對變數進行+1,再使用變數的值,也不是說著中說法不對,其實我們在使用過程中,確實與這個結論並不相違背,但是就是偶爾出現一些詭異的現象,讓我想去一探究竟。
很早之前就使用過javap,去驗證一些東西,比如建構函式,比如介面、列舉,但是也只是粗略的看一個大概,對於反編譯出來的一些彙編指令也是看個大概意思,沒有深究,這次就藉助javap這個指令,好好分析一下前自增和後自增的區別

先來第一輪驗證,程式碼很簡單:
在這裡插入圖片描述
然後通過javap反編譯看看指令:
在這裡插入圖片描述
為了便於理解,這裡對每一行指令進行解釋
Code:
0: iconst_1 //將常量1置於棧頂
1: istore_1 //將棧頂資料(即1)儲存到變數1(即i)中
2: iinc 1, 1 //對變數1進行+1操作,此時變數1的值是2
5: iconst_1 //將常量1置於棧頂
6: istore_2 //將棧頂資料(即1)儲存到變數1(即i)中
7: iinc 2, 1 //對變數2進行+1操作,此時變數2的值是2
10: return
很明顯,反編譯出來的指令時完全一樣的,所以,我們可以下個這樣的結論,單純的前自增和後自增的執行原理沒有任何區別。

有了第一輪的基礎之後,我們再來驗證第二輪,程式碼如下:
在這裡插入圖片描述
首選,這一段程式碼執行後的結果,我們都知道i = 1, j = 2
個我們之前接觸的那套理論依然不衝突,關鍵是有一個地方很多人想不明白,就是不管怎麼樣,你i最終還是自增了呀,怎麼還是1呢。通過反編譯的結果我們就可以很清晰的理解了。
在這裡插入圖片描述
再次解釋一下每一行指令的意思:
Code:
0: iconst_1 //將常量1置於棧頂
1: istore_1 //將棧頂資料儲存到變數i中
2: iload_1 //將變數i的值置於棧頂
3: iinc 1, 1 //對變數i進行+1操作,i的值為2
6: istore_1 //將棧頂資料(i自增前的值)儲存到變數i,i重新變為1
7: iconst_1 //將常量1置於棧頂
8: istore_2 //將棧頂資料儲存到變數j中
9: iinc 2, 1 //對變數j進行+1操縱,j的值為2
12: iload_2 //將j的值置於棧頂 (注意此時j的值已經是2)
13: istore_2 //將棧頂資料儲存到變數j中
14: return
所以很明顯,前自增和後自增在參與運算的時候有一個非常重要的區別,就是何時將變數的值置於棧頂
在這裡插入圖片描述


驗證到此結束,其實中間應該還加上兩個簡單一點的驗證,就是如下兩種:
1、
在這裡插入圖片描述
2、
在這裡插入圖片描述
不過,我的第二個驗證本身就包含這兩中情況中的特殊情況,所以直接跳過了,不是很明白的同學可以自己去驗證一下這兩種情況。