轉載自 這裡
前言 :
在Java中,要建立字串很方便 :
依Java命名慣例而言,String這個名稱首字大寫,無疑地應該是個類別,這代表了,str是參考至一個String的實例。有些書會說,這個寫法其實等同於以下的寫法,而且這樣有建立物件的明確語義 :
這並不是全部的事實。這句話比較像是 :
也就是先前的那行程式碼,其實JVM建立了兩個String實例。這意謂著,直接使用雙引號包括字元來建立字串,以及自行用new關鍵字建立字字串是不同的,這可以由以下的程式碼來驗證 :
==運算子會比較兩個參考名稱是否參考至同一物件,上面的程式片段會印出false,也就是str1與str2是參考至不同物件。直接使用雙引號包括字元來建立字串,JVM會自行在記憶體中使用一個字串池(String pool)來維護,只要雙引號含括的字元內容相同(序列相同,大小寫相同),無論在程式碼中出現幾次,在字串池中都只有一個實例! 下面這段程式碼可以驗證 :
這個程式碼片段會印出true,因為雙引號含括的內容都是Java這個字元序列,雖然程式碼中出現了兩次"Java",但在字串池中卻只有一個實例,只不過依程式碼所定義的,被str1與str2所參考著. 一般書籍都會說,要比較字串是否相等要使用equals()方法而不是==,這個意思是指比較字串所含字元序列的相等性,而非參考名稱所參考的記憶體位置相等性。下面這個程式碼會顯示true,因為str1與str2所參考之物件,其所含字元序列都相等 :
每個字串都是不可變動的,這表示你一旦建立字串,就不可以修改它的字元內容。字串的字元內容,是維護在String中的字元陣列中 :
下面這段程式碼,只不過是將字串內含字元陣列給另一個字串在內部複製或參考 :
其它的字串建構式也是類似的。String上還有個intern()方法,可以讓你將字串放入字串池,或者是從字串池中取得JVM所維護的字串。如果你呼叫它,則會使用equals()方法,比較字串池中是否有字元序列相同的字串,如果有則傳回,如果無則將該字串置入字串池. 所以下面這個程式碼執行結果會是true :
在Java中,可以使用+串接字串,例如 :
最後顯示的是JavaCool. 用+串接字串很方便,但要小心+會產生新的字串。這也不是全部的事實,因為它產生的更多,如果使用的是JDK5以上,可以實際反組譯看看 :
如果是JDK1.4以下,則會在JVM內部產生StringBuffer完成類似的字串附加動作。StringBuilder或StringBuffer, 內部也是使用自動增加的字元陣列來維護,若長度不夠,則會產生新的更長的字元陣列,然後作字元陣列複製的動作。所以若是有頻繁串接字串的動作,例如在迴圈 中串接SQL之類的,會有效能上的隱憂,應當避免! 不過下面這個稍微有點不同 :
執行結果一樣顯示JavaCool,不過反組譯它,你會發現編譯器很聰明 :
既然兩個都是雙引號括著,又直接使用+串接,那你要的不就是"JavaCool" ? 附帶一提的是,字串與物件之間也是可以使用+串接的!例如 :
這沒什麼!如果字串與物件使用+串接,其實最後會呼叫物件的toString()取得物件的字串描述,也就是說類似於 :
這也不完全是事實,上面只是比喻!編譯器(或JVM)作的更多:
至於StringBuilder的append()作了什麼,留待你自行去探索一下它的原始碼吧!
補充說明 :
* 延伸閱讀 String and memory leaks
* [ Java 小學堂 ] Java 世界裡 equals 與 == 的差別
前言 :
在Java中,要建立字串很方便 :
- String str = "Java";
- String str = new String("Java");
- String str1 = "Java";
- String str2 = new String(str1);
- String str1 = "Java";
- String str2 = new String(str1);
- System.out.println(str1 == str2);
- String str1 = "Java";
- String str2 = "Java";
- System.out.println(str1 == str2);
- String str1 = "Java";
- String str2 = new String(str1);
- System.out.println(str1.equals(str2)); // 結果為 true
- public final class String
- implements java.io.Serializable, Comparable
, CharSequence { - /** The value is used for character storage. */
- private final char value[];
- public String(String original) {
- int size = original.count;
- char[] originalValue = original.value;
- char[] v;
- if (originalValue.length > size) {
- v = Arrays.copyOfRange(originalValue, off, off+size);
- } else {
- v = originalValue;
- }
- this.offset = 0;
- this.count = size;
- this.value = v;
- }
- String str1 = "Java";
- String str2 = new String(str1);
- System.out.println(str1 == str2.intern());
- String str1 = "Java";
- String str2 = "Cool";
- String str3 = str1 + str2;
- System.out.println(str3);
- String s = "Java";
- String s1 = "Cool";
- String s2 = (new StringBuilder()).append(s).append(s1).toString();
- System.out.println(s2);
- String str = "Java" + "Cool";
- System.out.println(str);
- String s = "JavaCool";
- System.out.println(s);
- Map map = new HashMap();
- map.put("key", "value");
- System.out.println("Map: " + map);
- Map map = new HashMap();
- map.put("key", "value");
- System.out.println("Map: " + map.toString());
- HashMap hashmap = new HashMap();
- hashmap.put("key", "value");
- System.out.println(
- (new StringBuilder()).append("Map: ").append(hashmap).toString());
補充說明 :
* 延伸閱讀 String and memory leaks
* [ Java 小學堂 ] Java 世界裡 equals 與 == 的差別
This message was edited 4 times. Last update was at 28/02/2011 14:43:37
沒有留言:
張貼留言