隨筆-46  評論-64  文章-2  trackbacks-0
          new & valueof & 直接賦值的區別
          首先來看下面這段代碼
          public static void main(String[] args) {
          ??String s1 = "s1";
          ??String s2 = new String("s2");
          ??String s3 = String.valueOf(12345);
          }
          ?
          編譯成class文件之后,使用eclipse class file viewer查看
          ?
          ? // Method descriptor #15 ([Ljava/lang/String;)V
          ? // Stack: 3, Locals: 4
          ? public static void main(java.lang.String[] args);
          ???? 0? ldc <String "s1"> [16]
          ???? 2? astore_1 [s1]

          ???? 3? new java.lang.String [18]
          ???? 6? dup
          ???? 7? ldc <String "s2"> [20]
          ???? 9? invokespecial java.lang.String(java.lang.String) [22]
          ??? 12? astore_2 [s2]
          ??? 13? sipush 12345
          ??? 16? invokestatic java.lang.String.valueOf(int) : java.lang.String [25]
          ??? 19? astore_3 [s3]

          ??? 20? return
          ????? Line numbers:
          ??????? [pc: 0, line: 12]
          ??????? [pc: 3, line: 13]
          ??????? [pc: 13, line: 14]
          ??????? [pc: 20, line: 20]
          ????? Local variable table:
          ??????? [pc: 0, pc: 21] local: args index: 0 type: java.lang.String[]
          ??????? [pc: 3, pc: 21] local: s1 index: 1 type: java.lang.String
          ??????? [pc: 13, pc: 21] local: s2 index: 2 type: java.lang.String
          ??????? [pc: 20, pc: 21] local: s3 index: 3 type: java.lang.String
          }
          ?
          對于第一行代碼 String s1 = "s1"; 編譯成字節碼之后,對應兩條指令,
          1. ldc指令從運行時常量池push一個值到Frame的操作數棧上面,這個值在這里就是"s1"字符串的引用,
          2. astore指令將objectref存儲到局部變量,這里也就是存儲到局部變量s1。
          ?
          對于第二行代碼???String s2 = new String("s2");編譯成字節碼之后,對于的指令也用高亮標注出來了,這里把操作數棧的情況畫了出來,希望能幫助理解。橙色標注的為棧頂元素。
          1. new指令會在堆上創建對象,操作數棧里壓入創建的objectref,
            ?
            objectref
            ...
          2. dup指令復制操作數棧頂的元素,?
            objectref
            objectref
            ...
          3. ldc指令依然是從常量池push一個值到Frame的操作數棧上,這個值是"s2"字符串的引用。?
            "s2"_ref
            objectref
            objectref
            ...
          4. invokespecial 指令調用一個方法,這里就是調用String的構造函數,調用完成之后棧上還有一個objectref?
            objectref
            ...
          5. astore指令將objectref存儲到局部變量,這里也就是存儲到局部變量s2。?
            ????????????
            ...
          ?
          對于第三行代碼??String s3 = String.valueOf(12345); 編譯成字節碼之后對應的指令,
          1. sipush 將 12345 壓棧
          2. invokestatic 調用 String.valueof(int) 方法
          3. astore 將棧頂的對象引用存儲到本地變量s3 (這里不再深究這個棧頂元素是怎么來的了)
          ?
          PMD檢查代碼的時候,有這樣的warning: Avoid instantiating?String objects.Call String.valueOf() instead. PMD給出的原因是In JDK 1.5, calling new String() causes memory allocation. String.valueOf() is more memory friendly.
          ?
          經過上面的分解,我們應該知道原因了,以后寫代碼的時候,初始化一個字符串,??String s1 = "s1"; 這樣的代碼肯定比??String s2 = new String("s2");代碼強,將其他類型的值轉換成String的時候,valueof方法比new方法效率也高。

          ?
          備注:
          A frame is used to store data and partial results(局部變量,操作數棧), as well as to perform dynamic linking , return values for methods, and dispatch exceptions.
          ?
          ldc指令的操作數棧: ...->...,value (value是int,float 或者 string 類型的引用)
          astore的操作數棧: ...,objectref->...
          new指令的操作數棧: ...->...,objectref
          dup指令的操作數棧: ...,value->...,value,value
          invokespecial的操作數棧: ...,objectref, [agr1,[arg2...]]->...
          invloestatic的操作數棧:..., [arg1, [arg2...]]?-> ...

          ?
          如果要理解的更透徹建議閱讀以下參考資料:
          posted on 2008-07-28 14:27 jht 閱讀(1707) 評論(1)  編輯  收藏 所屬分類: J2SE

          評論:
          # re: new & valueof & 直接賦值的區別 2008-07-28 23:29 | 隔葉黃鶯
          其實不用到字節碼里去,看 valueOf() 方法的源代碼大家就能明白是怎么回事,應該用 valueOf() 而不是 new.  回復  更多評論
            
          主站蜘蛛池模板: 开远市| 宁夏| 修文县| 延川县| 烟台市| 兴山县| 高淳县| 普兰店市| 呼伦贝尔市| 红河县| 武平县| 托克托县| 乃东县| 长沙市| 策勒县| 和平县| 锡林郭勒盟| 洮南市| 开封市| 黑河市| 济南市| 洱源县| 区。| 阿尔山市| 通山县| 始兴县| 洛隆县| 怀安县| 鄂温| 柳河县| 泽州县| 彭水| 宾川县| 揭西县| 响水县| 景东| 龙山县| 南京市| 迭部县| 荔浦县| 万荣县|