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"; 編譯成字節碼之后,對應兩條指令,
-
ldc指令從運行時常量池push一個值到Frame的操作數棧上面,這個值在這里就是"s1"字符串的引用,
-
astore指令將objectref存儲到局部變量,這里也就是存儲到局部變量s1。
?
對于第二行代碼???String s2 = new String("s2");編譯成字節碼之后,對于的指令也用高亮標注出來了,這里把操作數棧的情況畫了出來,希望能幫助理解。橙色標注的為棧頂元素。
-
new指令會在堆上創建對象,操作數棧里壓入創建的objectref,
-
-
ldc指令依然是從常量池push一個值到Frame的操作數棧上,這個值是"s2"字符串的引用。?
|
"s2"_ref |
objectref |
objectref |
... |
-
invokespecial 指令調用一個方法,這里就是調用String的構造函數,調用完成之后棧上還有一個objectref?
-
astore指令將objectref存儲到局部變量,這里也就是存儲到局部變量s2。?
?
對于第三行代碼??String s3 = String.valueOf(12345); 編譯成字節碼之后對應的指令,
-
sipush 將 12345 壓棧
-
invokestatic 調用 String.valueof(int) 方法
-
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 閱讀(1704)
評論(1) 編輯 收藏 所屬分類:
J2SE