java String 創建的深入理解


Java字符串類(java.lang.String)是Java中使用最多的類,也是最爲特殊的一個類,很多時候,我們對它既熟悉又陌生。
 
一、從根本上認識java.lang.String類和String池
 
首先,我建議先看看String類的源碼實現,這是從本質上認識String類的根本出發點。從中可以看到:
1、String類是final的,不可被繼承。public final class String。
2、String類是的本質是字符數組char[], 並且其值不可改變。private final char value[];
然後打開String類的API文檔,可以發現:
3、String類對象有個特殊的創建的方式,就是直接指定比如String x = "abc","abc"就表示一個字符串對象。而x是"abc"對象的地址,也叫做"abc"對象的引用。
4、String對象可以通過“+”串聯。串聯後會生成新的字符串。也可以通過concat()來串聯,這個後面會講述。
6、Java運行時會維護一個String Pool(String池),JavaDoc翻譯很模糊“字符串緩衝區”。String池用來存放運行時中產生的各種字符串,並且池中的字符串的內容不重複。而一般對象不存在這個緩衝池,並且創建的對象僅僅存在於方法的堆棧區。下面是個系統內存示意圖:

7、創建字符串的方式很多,歸納起來有三類:
其一,使用new關鍵字創建字符串,比如String s1 = new String("abc");
其二,直接指定。比如String s2 = "abc";
其三,使用串聯生成新的字符串。比如String s3 = "ab" + "c";
二、String對象的創建
 
String對象的創建也很講究,關鍵是要明白其原理。
原理1:當使用任何方式來創建一個字符串對象s時,Java運行時(運行中JVM)會拿着這個X在String池中找是否存在內容相同的字符串對象,如果不存在,則在池中創建一個字符串s,否則,不在池中添加。
 
原理2:Java中,只要使用new關鍵字來創建對象,則一定會(在堆區或棧區)創建一個新的對象。
 
原理3:使用直接指定或者使用純字符串串聯來創建String對象,則僅僅會檢查維護String池中的字符串,池中沒有就在池中創建一個,有則罷了!但絕不會在堆棧區再去創建該String對象。
 
原理4:使用包含變量的表達式來創建String對象,則不僅會檢查維護String池,而且還會在堆棧區創建一個String對象。
 
另外,String的intern()方法是一個本地方法,定義爲public native String intern(); intern()方法的價值在於讓開發者能將注意力集中到String池上。當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並且返回此 String 對象的引用。

/**
* Created by IntelliJ IDEA.<br>
* <b>User</b>: leizhimin<br>
* <b>Date</b>: 2008-6-2 22:14:16<br>
* <b>Note</b>: Please add comment here!
*/
public class StringTest {
    public static void main(String args[]) {
        //在池中和堆中分別創建String對象"abc",s1指向堆中對象
        String s1 = new String("abc");
        //s2直接指向池中對象"abc"
        String s2 = "abc";
        //在堆中新創建"abc"對象,s3指向該對象
        String s3 = new String("abc");
        //在池中創建對象"ab" 和 "c",並且s4指向池中對象"abc"
        String s4 = "ab" + "c";
        //c指向池中對象"c"
        String c = "c";
        //在堆中創建新的對象"abc",並且s5指向該對象
        String s5 = "ab" + c;

        String s6 = "ab".concat("c");
        String s7 = "ab".concat(c);

        System.out.println("------------實串-----------");
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s3); //false
        System.out.println(s2 == s3); //false
        System.out.println(s2 == s4); //true
        System.out.println(s2 == s5); //false
        System.out.println(s2 == s6); //false
        System.out.println(s2 == s7); //false

        String b1 = new String("");
        String b2 = "";
        String b3 = new String("");
        String b4 = "".intern();
        String b5 = "" + "";
        String b6 = "".concat("");
        String b7 = "  ".trim();
        String b8 = "  ";
        String b9 = "    ".trim();

        System.out.println("------------空串-----------");
        System.out.println(b1 == b2);  //false
        System.out.println(b1 == b3);  //false
        System.out.println(b2 == b3);  //false
        System.out.println(b2 == b4);  //true
        System.out.println(b2 == b5);  //true*
        System.out.println(b2 == b6);  //true*
        System.out.println(b2 == b7);  //false*
        System.out.println("-----a----");
        System.out.println(b2.equals(b7));  //true
        System.out.println(b7 == b8);  //false
        System.out.println(b7 == b9);  //false
        System.out.println(b7.equals(b9)); //true
        System.out.println(b9 == null);//false

        System.out.println("b8.trim():");
        for (byte b : b8.getBytes()) {
            System.out.print(">>>" + (int) b + " ");
        }
        System.out.println("\nb8.trim():");
        for (byte b : b8.trim().getBytes()) {
            System.out.print(">>>" + (int) b + " ");
        }
        System.out.println("\nb9.trim():");
        for (byte b : b9.trim().getBytes()) {
            System.out.print(">>>" + (int) b + " ");
        }
    }
}

發佈了21 篇原創文章 · 獲贊 16 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章