public class AddTest { public static void main(String[] args) { int i = 0; i = i++; System.out.println("i=" + i); } }
輸出結果是多少呢?本身思考後繼續往下看效果更好哦java
正確答案是 0面試
若是能徹底想明白,能夠結束往下閱讀了。若是有疑惑,請繼續讀下去3d
我剛看到這道題,給的答案也是 1,由於我以往的理解是 i++ 是先賦值,而後再進行 ++ 操做,在賦值時,i 確實爲 0,但 i 應該完成了自增操做,輸出的 i 應該爲 1 呀,本身也驗證了一下,的確是 0。想不明白那就看看字節碼吧,也許從中能找到答案code
先經過 javac AddTest.java 生成 AddTest.class 文件,而後經過 javap -v AddTest.class 查看具體的字節碼(只截取了部分)對象
首先說明左邊的數字序號表示字節碼的偏移量(偏移量和前面的字節碼長度有關),即當前字節碼所在的位置,很像行號,但不是行號blog
下面咱們用圖解的方式分析下主要步驟 it
經過圖解咱們發現操做數棧中的 0 把局部變量表 1 位置的 1 覆蓋了,因此最後輸出的結果是 0class
xconst_n (x爲 i 表示整數,l 表示長整數,f 表示浮點數,d 表示雙精度浮點數,a 表示對象引用;n 爲 0~5):常量入棧指令,表明將 n 壓入棧變量
xload_n(x 取值和 const 同樣,n 爲 0~3):局部變量壓棧指令,將第n個局部變量壓入操做數棧bfc
xstore_n(x 取值和 const同樣,n 爲 0~3):出棧裝入局部變量表指令,從操做數棧中彈出,賦值給局部變量 n
iinc arg1,arg2:對給定的局部變量作自增操做。執行過程當中不須要修改操做數棧。接收兩個操做數,第一個爲局部變量表的位置,第二個爲累加數
說完了 i++ 就不能落下它的好兄弟 ++i
public class Add2Test { public static void main(String[] args) { int i = 0; i = ++i; System.out.println("i=" + i); } }
這個結果我想你們都能答對,輸出 1,可是我仍是想把 ++i 的字節碼打出來,而後和 i++ 的進行對比
字節碼圖解以下所示
咱們把這兩個圖放在一塊兒對比看下
爲什麼一道簡單的 i++ 的輸出問題,我都能弄錯?追根是由於對字節碼底層的不瞭解,雖然咱們經過字節碼和畫圖分析出了緣由,但這並不夠,最好作到看到代碼,對應的字節碼就映射到腦中。說實話,對我來講挺難的。須要不斷練習。懂了字節碼會對 Java 中更多底層的知識不止知其然,更知其因此然。
歡迎關注公衆號 【天天曬白牙】,獲取最新文章,咱們一塊兒交流,共同進步!