中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

字節碼層面理解java中i++和++i的區別

發布時間:2020-06-28 14:45:42 來源:網絡 閱讀:641 作者:nineteens 欄目:編程語言

  還是讓我們從一道面試題說起吧,代碼如下,你知道方法執行最后會輸出什么嗎?

  public static void main(String[] args) {

  int i = 0;

  for (int j = 0; j < 50; j++) {

  i = i++;

  }

  System.out.println(i);

  }

  不賣關子,最后輸出結果是0,而不是50,不知道跟你的認知是否一致。

  直接上字節碼,讓我們從字節碼層面看看i++背后的邏輯。

  public static void main(java.lang.String[]);

  descriptor: ([Ljava/lang/String;)V

  flags: ACC_PUBLIC, ACC_STATIC

  Code:

  stack=2, locals=3, args_size=1

  0: iconst_0

  1: istore_1

  2: iconst_0

  3: istore_2

  4: iload_2

  5: bipush 50

  7: if_icmpge 21

  10: iload_1

  11: iinc 1, 1

  14: istore_1

  15: iinc 2, 1

  18: goto 4

  21: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

  24: iload_1

  25: invokevirtual #3 // Method java/io/PrintStream.println:(I)V

  28: return

  先拋出這個方法局部變量表

  0  1  2

  args  i  j

  pc 0~1兩個指令,為下標為1的局部變量賦值為0,也就是局部變量i

  pc 2~3兩個指令,為下表為2的局部變量賦值為0,也就是局部變量j

  pc 4~7三個指令,取局部變量j的值與50比較,如果j>=50,跳轉到pc=21的指令處,如果不滿足則順序往下執行

  pc 10~14三個指令,是i=i++這行代碼編譯后的指令。在jvm中,局部變量表和操作數棧是兩個不同的存儲數據的內存區域。iload_1表示將局部變量表中下標為1的變量,也就是變量i的值復制一份,加載到操作數棧頂,innc 1,1 指令則將局部變量表中變量i的值加1再寫回局部變量表中變量i的位置,istore_1則將棧頂的數據覆蓋局部變量表中變量i的位置,所以執行完這3個命令后,變量i的值并沒有發生變化。用偽代碼來表示這三個指令的邏輯就是這樣

  int stack_top = local_variable[1];//把下標為1的局部變量加載到棧頂

  local_variable[1] = local_variable[1] + 1;//下標為1的局部變量自增1

  local_variable[1] = stack_top;//用棧頂的值覆蓋下標為1的局部變量

  pc 15指令iinc 2,1 將變量j自增1

  pc 18指令goto 4,程序重新從pc=4的地方開始執行

  pc 21~25三個指令,就是打印下標為1的局部變量,也就是打印變量i

  所以,從pc10~14三個指令,可以看出變量i=i++這行代碼不會改變變量i的值,因此最后打印結果是0。

  如果將 i=i++ 改成 i=++i,結果會是怎樣呢?

  public static void main(String[] args) {

  int i = 0;鄭州好的婦科醫院 http://www.zzkedayy.com/

  for (int j = 0; j < 50; j++) {

  i = ++i;

  }

  System.out.println(i);

  }

  輸出結果是50,還是直接看字節碼

  public static void main(java.lang.String[]);

  descriptor: ([Ljava/lang/String;)V

  flags: ACC_PUBLIC, ACC_STATIC

  Code:

  stack=2, locals=3, args_size=1

  0: iconst_0

  1: istore_1

  2: iconst_0

  3: istore_2

  4: iload_2

  5: bipush 50

  7: if_icmpge 21

  10: iinc 1, 1

  13: iload_1

  14: istore_1

  15: iinc 2, 1

  18: goto 4

  21: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

  24: iload_1

  25: invokevirtual #3 // Method java/io/PrintStream.println:(I)V

  28: return

  除了指令10~14,對應的代碼就是 i=++i,其他部分跟上面的字節碼指令一樣,所以我們只看不一樣的部分。

  pc 10 innc 1,1 這里先執行自增指令,將下標為1的局部變量i的值自增1

  pc 13 iload_1 將下標為1的局部變量i的值加載到操作數棧頂

  pc 14istore_1 將操作數棧頂的值覆蓋下標為1的局部變量i的值

  用偽代碼來表示這段邏輯就是這樣

  local_variable[1] = local_variable[1] + 1;//下標為1的局部變量自增1

  int stack_top = local_variable[1];//把下標為1的局部變量加載到棧頂

  local_variable[1] = stack_top;//用棧頂的值覆蓋下標為1的局部變量

  所以,從pc10~14三個指令,可以看出變量 i=++i 這行代碼會使i的值增加1,因此最后打印結果是50。

  與i++對應的指令不同的地方是,++i會先執行innc 1,1指令,這條指令會是i的值增加1,然后再參與計算。而i++會先將i的值保存到另外一個地方,然后再對i自增1,但是i=i++的賦值(也就是=)會用已保存的i的舊值覆蓋i的新值,所以i=i++,i的值并不會變。

  總結:講解了i=i++和i=++i的字節碼底層原理。

  不知道朋友你理解了沒有,試試這道題輸出結果是什么

  int i = 0;

  int result = i++ + ++i + i++;

  System.out.println(result);


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

庐江县| 碌曲县| 安义县| 惠安县| 米林县| 收藏| 来凤县| 莲花县| 开平市| 京山县| 浦东新区| 福贡县| 女性| 枝江市| 台江县| 辉南县| 左贡县| 洮南市| 土默特右旗| 渭源县| 农安县| 武冈市| 阿巴嘎旗| 永兴县| 达州市| 沙湾县| 榆社县| 克东县| 进贤县| 万载县| 靖安县| 沧州市| 峨边| 宁南县| 克拉玛依市| 五寨县| 惠水县| 嘉禾县| 辽宁省| 尉犁县| 安阳县|