Java String常用方法詳解
51CTO層介紹過“Java String的常用方法及使用注意事項”,本文首先講述了Java String的常用方法,用String 常量池問題的四個例子對String對象的intern方法理解和分析。
String中的final用法和理解
- final StringBuffer a = new StringBuffer("111");
- final StringBuffer b = new StringBuffer("222");
- a=b;//此句編譯不通過
- final StringBuffer a = new StringBuffer("111");
- a.append("222");//編譯通過
可見,final只對引用的"值"(即內存地址)有效,它迫使引用只能指向初始指向的那個對象,改變它的指向會導致編譯期錯誤。至于它所指向的對象的變化,final是不負責的。
String常量池問題的四個例子
下面是幾個常見例子的比較分析和理解:
- [1]
- String a = "a1";
- String b = "a" + 1;
- System.out.println((a == b)); //result = true
- String a = "atrue";
- String b = "a" + "true";
- System.out.println((a == b)); //result = true
- String a = "a3.4";
- String b = "a" + 3.4;
- System.out.println((a == b)); //result = true
分析:JVM對于字符串常量的"+"號連接,將程序編譯期,JVM就將常量字符串的"+"連接優化為連接后的值,拿"a" + 1來說,經編譯器優化后在class中就已經是a1。在編譯期其字符串常量的值就確定下來,故上面程序最終的結果都為true。
- [2]
- String a = "ab";
- String bb = "b";
- String b = "a" + bb;
- System.out.println((a == b)); //result = false
分析:JVM對于字符串引用,由于在字符串的"+"連接中,有字符串引用存在,而引用的值在程序編譯期是無法確定的,即"a" + bb無法被編譯器優化,只有在程序運行期來動態分配并將連接后的新地址賦給b。所以上面程序的結果也就為false。
- [3]
- String a = "ab";
- final String bb = "b";
- String b = "a" + bb;
- System.out.println((a == b)); //result = true
分析:和[3]中唯一不同的是bb字符串加了final修飾,對于final修飾的變量,它在編譯時被解析為常量值的一個本地拷貝存儲到自己的常量池中或嵌入到它的字節碼流中。所以此時的"a" + bb和"a" + "b"效果是一樣的。故上面程序的結果為true。
- [4]
- String a = "ab";
- final String bb = getBB();
- String b = "a" + bb;
- System.out.println((a == b)); //result = false
- private static String getBB() {
- return "b";
- }
分析:JVM對于字符串引用bb,它的值在編譯期無法確定,只有在程序運行期調用方法后,將方法的返回值和"a"來動態連接并分配地址為b,故上面程序的結果為false。
通過上面4個例子可以得出得知:
- String s = "a" + "b" + "c";
就等價于String s = "abc";
- String a = "a";
- String b = "b";
- String c = "c";
- String s = a + b + c;
這個就不一樣了,最終結果等于:
- StringBuffer temp = new StringBuffer();
- temp.append(a).append(b).append(c);
- String s = temp.toString();
由上面的分析結果,可就不難推斷出String 采用連接運算符(+)效率低下原因分析,形如這樣的代碼:
- public class Test {
- public static void main(String args[]) {
- String s = null;
- for(int i = 0; i < 100; i++) {
- s += "a";
- }
- }
- }
每做一次 + 就產生個StringBuilder對象,然后append后就扔掉。下次循環再到達時重新產生個StringBuilder對象,然后 append 字符串,如此循環直至結束。 如果我們直接采用 StringBuilder 對象進行 append 的話,我們可以節省 N - 1 次創建和銷毀對象的時間。所以對于在循環中要進行字符串連接的應用,一般都是用StringBuffer或StringBulider對象來進行append操作。
String對象的intern方法理解和分析
- public class Test4 {
- private static String a = "ab";
- public static void main(String[] args){
- String s1 = "a";
- String s2 = "b";
- String s = s1 + s2;
- System.out.println(s == a);//false
- System.out.println(s.intern() == a);//true
- }
- }
這里用到Java里面是一個常量池的問題。對于s1+s2操作,其實是在堆里面重新創建了一個新的對象,s保存的是這個新對象在堆空間的的內容,所以s與a的值是不相等的。而當調用s.intern()方法,卻可以返回s在常量池中的地址值,因為a的值存儲在常量池中,故s.intern和a的值相等。






















