<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從JVM層面來解釋i++和++i的真正區(qū)別

          共 13597字,需瀏覽 28分鐘

           ·

          2021-07-07 23:52

          前言

          如果只用普通的知識解釋i++和++i的話

          • i++ 先將i賦值再++
          • ++i 先++再賦值

          但是這簡單的回答并不能入吸引面試官的眼球,如果用java字節(jié)碼指令分析則效果完全不同。

          代碼實現(xiàn)

          public class OperandStackTest {
          /**
              程序員面試過程中, 常見的i++和++i 的區(qū)別
               */

              public static void add(){
                  //第1類問題:
                  int i1 = 10;
                  i1++;
                  System.out.println(i1);//11

                  int i2 = 10;
                  ++i2;
                  System.out.println(i2);//11

                  //第2類問題:
                  int i3 = 10;
                  int i4 = i3++;
                  System.out.println(i3);//11
                  System.out.println(i4);//10

                  int i5 = 10;
                  int i6 = ++i5;
                  System.out.println(i5);//11
                  System.out.println(i6);//11

                  //第3類問題:
                  int i7 = 10;
                  i7 = i7++;
                  System.out.println(i7);//10

                  int i8 = 10;
                  i8 = ++i8;
                  System.out.println(i8);//11

                  //第4類問題:
                  int i9 = 10;
                  int i10 = i9++ + ++i9;//10+12
                  System.out.println(i9);//12
                  System.out.println(i10);//22
              }

              public static void main(String[] args) {
                  add();
              }
          }

          運行結果

          字節(jié)碼指令

          通過javap -v out目錄下的class文件名 在終端運行得到如下結果

           public static void add();
              descriptor: ()V
              flags: ACC_PUBLIC, ACC_STATIC
              Code:
                stack=2, locals=10, args_size=0
                   0: bipush        10
                   2: istore_0
                   3: iinc          01
                   6: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                   9: iload_0
                  10: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  13: bipush        10
                  15: istore_1
                  16: iinc          11
                  19: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  22: iload_1
                  23: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  26: bipush        10
                  28: istore_2
                  29: iload_2
                  30: iinc          21
                  33: istore_3
                  34: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  37: iload_2
                  38: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  41: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  44: iload_3
                  45: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  48: bipush        10
                  50: istore        4
                  52: iinc          41
                  55: iload         4
                  57: istore        5
                  59: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  62: iload         4
                  64: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  67: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  70: iload         5
                  72: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  75: bipush        10
                  77: istore        6
                  79: iload         6
                  81: iinc          61
                  84: istore        6
                  86: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                  89: iload         6
                  91: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                  94: bipush        10
                  96: istore        7
                  98: iinc          71
                 101: iload         7
                 103: istore        7
                 105: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                 108: iload         7
                 110: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                 113: bipush        10
                 115: istore        8
                 117: iload         8
                 119: iinc          81
                 122: iinc          81
                 125: iload         8
                 127: iadd
                 128: istore        9
                 130: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                 133: iload         8
                 135: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                 138: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
                 141: iload         9
                 143: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
                 146return

          解釋以上運行結果

          第一類問題

          對應的指令為

          先將i1的值為10入棧(bipush),然后將int類型的值從棧中存到局部變量表0的位置,然后執(zhí)行iinc將0位置的值+1,然后將局部變量表0位置的數(shù)入棧執(zhí)行輸出操作

          所以i1的值為11

          先將i2的值為10入棧(bipush),然后將int類型的值從棧中存到局部變量表1的位置,然后執(zhí)行iinc將1位置的值+1,然后將局部變量表1位置的數(shù)入棧執(zhí)行輸出操作

          所以i2的值為11

          總結

          由于沒有賦值操作,區(qū)別不大。

          第二類問題

          先將i3入棧存儲到局部變量表2的位置,然后將它入棧,執(zhí)行iinc將2位置的值加一,i4存儲到局部表量表3的位置

          所以i3是11,i4還是10

          將i5入棧存儲到局部變量表4的位置,由于是++i所以先iinc將4位置的值加一,然后將局部變量表4的值入棧,執(zhí)行賦值操作,所以都是11

          第三類問題

          先將i7入棧,然后存到局部變量表6的位置,先把i6入棧,然后把6處的值加一,由于又將這個值存儲到局部變量表6處,所以產(chǎn)生覆蓋又把值變?yōu)?0。

          而++i不會產(chǎn)生覆蓋先執(zhí)行加一然后再把值入棧,在賦值給局部變量表中,所以i8為11。另外,歡迎關注公眾號Java筆記蝦,后臺回復“后端面試”,送你一份面試題寶典!

          第四類問題

          先將i9=10入棧,然后存在局部變量表8的位置

          int i10 = i9++ + ++i9;

          先iload將8位置的i9入棧然后執(zhí)行iinc將8處的i9加一,然后執(zhí)行++i9,在將8處的i9加一

          此時i9=10+1+1為12,然后將8位置的i9入棧,執(zhí)行add將棧中的兩i9相加,得到的值存儲到局部變量表9的位置

          所以i10=10+12(i9++后還是10,++i9后是12,因為執(zhí)行了兩次iinc操作)

          然后調用虛方法和靜態(tài)方法,在將9處的值入棧執(zhí)行輸出語句

          (感謝閱讀,希望對你所有幫助)
          來源:https://blog.csdn.net/weixin_45706762/

          推薦閱讀:

          世界的真實格局分析,地球人類社會底層運行原理

          企業(yè)IT技術架構規(guī)劃方案

          論數(shù)字化轉型——轉什么,如何轉?

          企業(yè)10大管理流程圖,數(shù)字化轉型從業(yè)者必備!

          【中臺實踐】華為大數(shù)據(jù)中臺架構分享.pdf

          華為的數(shù)字化轉型方法論

          華為如何實施數(shù)字化轉型(附PPT)

          超詳細280頁Docker實戰(zhàn)文檔!開放下載

          華為大數(shù)據(jù)解決方案(PPT)

          瀏覽 82
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色视频网址 | av中文字幕在线播放 | 精品 熟女 国产 探花 AV | 99国产在线观看免费 | 亚洲黄色五月天 |