11.27 問:int i = 0;i = i++;最後i是幾?

問:int i = 0;i = i++;最後i是幾?

輸出結果是多少呢?自己思考後繼續往下看效果更好哦

..................................

......................................

正確答案是 0

如果能完全想明白,可以結束往下閱讀了。如果有疑惑,請繼續讀下去

我剛看到這道題,給的答案也是 1,因為我以往的理解是 i++ 是先賦值,然後再進行 ++ 操作,在賦值時,i 確實為 0,但 i 應該完成了自增操作,輸出的 i 應該為 1 呀,自己也驗證了一下,的確是 0。想不明白那就看看字節碼吧,也許從中能找到答案

先通過 javac AddTest.java 生成 AddTest.class 文件,然後通過 javap -v AddTest.class 查看具體的字節碼(只截取了部分)

問:int i = 0;i = i++;最後i是幾?

i++字節碼

首先說明左邊的數字序號表示字節碼的偏移量(偏移量和前面的字節碼長度有關),即當前字節碼所在的位置,很像行號,但不是行號

下面我們用圖解的方式分析下主要步驟

問:int i = 0;i = i++;最後i是幾?

i++字節碼圖解

通過圖解我們發現操作數棧中的 0 把局部變量表 1 位置的 1 覆蓋了,所以最後輸出的結果是 0

指令說明

xconst_n (x為 i 表示整數,l 表示長整數,f 表示浮點數,d 表示雙精度浮點數,a 表示對象引用;n 為 0~5):常量入棧指令,代表將 n 壓入棧

xload_n(x 取值和 const 一樣,n 為 0~3):局部變量壓棧指令,將第n個局部變量壓入操作數棧

xstore_n(x 取值和 const一樣,n 為 0~3):出棧裝入局部變量表指令,從操作數棧中彈出,賦值給局部變量 n

iinc arg1,arg2:對給定的局部變量做自增操作。執行過程中不需要修改操作數棧。接收兩個操作數,第一個為局部變量表的位置,第二個為累加數

++i 呢?

說完了 i++ 就不能落下它的好兄弟 ++i

問:int i = 0;i = i++;最後i是幾?

這個結果我想大家都能答對,輸出 1,但是我還是想把 ++i 的字節碼打出來,然後和 i++ 的進行對比

問:int i = 0;i = i++;最後i是幾?

++i字節碼

字節碼圖解如下所示

問:int i = 0;i = i++;最後i是幾?

++i字節碼圖解

i++ 與 ++i 對比

我們把這兩個圖放在一起對比看下

問:int i = 0;i = i++;最後i是幾?

對比

反思

為何一道簡單的 i++ 的輸出問題,我都能弄錯?追根是因為對字節碼底層的不瞭解,雖然我們通過字節碼和畫圖分析出了原因,但這並不夠,最好做到看到代碼,對應的字節碼就映射到腦中。說實話,對我來說挺難的。需要不斷練習。懂了字節碼會對 Java 中更多底層的知識不止知其然,更知其所以然。

思考題

switch-case 是如何支持 String 類型的?

try-catch-finally 中 finally 裡面的代碼為何一定會執行?

————————————————

原文鏈接:https://blog.csdn.net/dam454450872/article/details/103231844


分享到:


相關文章: