java-字符串

在Java中,要建立字串很方便:
String str = "Java";

依Java命名慣例而言,String這個名稱首字大寫,無疑地應該是個類別,這代表了,str是參考至一個String的實例。有些書會說,這個寫法其實等同於以下的寫法,而且這樣有建立物件的明確語義:
String str = new String("Java");

這並不是全部的事實。這句話比較像是:
String str1 = "Java";
String str2 = new String(str1);

也就是先前的那行程式碼,其實JVM建立了兩個String實例。這意謂著,直接使用雙引號包括字元來建立字串,以及自行用new關鍵字建立字字串是不同的,這可以由以下的程式碼來驗證:
String str1 = "Java";
String str2 = new String(str1);
System.out.println(str1 == str2);

==運算子會比較兩個參考名稱是否參考至同一物件,上面的程式片段會印出false,也就是str1與str2是參考至不同物件。直接使用雙引號包括字元來建立字串,JVM會自行在記憶體中使用一個字串池(String pool)來維護,只要雙引號含括的字元內容相同(序列相同,大小寫相同),無論在程式碼中出現幾次,在字串池中都只有一個實例。

下面這段程式碼可以驗證:
String str1 = "Java";
String str2 = "Java";
System.out.println(str1 == str2);

這個程式碼片段會印出true,因為雙引號含括的內容都是Java這個字元序列,雖然程式碼中出現了兩次"Java",但在字串池中卻只有一個實例,只不過依程式碼所定義的,被str1與str2所參考著。

一般書籍都會說,要比較字串是否相等要使用equals()方法而不是==,這個意思是指比較字串所含字元序列的相等性,而非參考名稱所參考的記憶體位置相等性。下面這個程式碼會顯示true,因為str1與str2所參考之物件,其所含字元序列都相等:
String str1 = "Java";
String str2 = new String(str1);
System.out.println(str1.equals(str2));

每個字串都是不可變動的,這表示你一旦建立字串,就不可以修改它的字元內容。字串的字元內容,是維護在String中的字元陣列中:
public final class String
    implements java.io.Serializable, Comparable<String>, 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上還有個intern()方法,可以讓你將字串放入字串池,或者是從字串池中取得JVM所維護的字串。如果你呼叫它,則會使用equals()方法,比較字串池中是否有字元序列相同的字串,如果有則傳回,如果無則將該字串置入字串池。

所以下面這個程式碼執行結果會是true:
String str1 = "Java";
String str2 = new String(str1);
System.out.println(str1 == str2.intern());

在Java中,可以使用+串接字串,例如:
String str1 = "Java";
String str2 = "Cool";
String str3 = str1 + str2;
System.out.println(str3);

最後顯示的是JavaCool。一應該都會告訴你,用+串接字串很方便,但要小心+會產生新的字串。這也不是全部的事實,因為它產生的更多,如果使用的是JDK5以上,可以實際反組譯看看:
String s = "Java";
String s1 = "Cool";
String s2 = (new StringBuilder()).append(s).append(s1).toString();
System.out.println(s2);

如果是JDK1.4以下,則會在JVM內部產生StringBuffer完成類似的字串附加動作。StringBuilder或StringBuffer,內部也是使用自動增加的字元陣列來維護,若長度不夠,則會產生新的更長的字元陣列,然後作字元陣列複製的動作。所以若是有頻繁串接字串的動作,例如在迴圈中串接SQL之類的,會有效能上的隱憂,應當避免。

不過下面這個稍微有點不同:
String str = "Java" + "Cool";
System.out.println(str);

執行結果一樣顯示JavaCool,不過反組譯它,你會發現編譯器很聰明:
String s = "JavaCool";
System.out.println(s);

既然兩個都是雙引號括著,又直接使用+串接,那你要的不就是"JavaCool"?

附帶一提的是,字串與物件之間也是可以使用+串接的!例如:
Map map = new HashMap();
map.put("key", "value");
System.out.println("Map: " + map);

這沒什麼!如果字串與物件使用+串接,其實最後會呼叫物件的toString()取得物件的字串描述,也就是說類似於:
Map map = new HashMap();
map.put("key", "value");
System.out.println("Map: " + map.toString());

這也不完全是事實,上面只是比喻!編譯器(或JVM)作的更多:
HashMap hashmap = new HashMap();
hashmap.put("key", "value");
System.out.println(
        (new StringBuilder()).append("Map: ").append(hashmap).toString());


至於StringBuilder的append()作了什麼,留待你自行去探索一下它的原始碼吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值