Java源碼解析:String

在Java編程中, String類型使用特別頻繁。但是要發揮String的作用,需要對String源碼深入理解,才能寫出高質量的代碼。

C語言不存在字符串類型,但可用字符數組表示字符串。萬變不離其宗,String的底層是基於字符數組,並且封裝了操作字符串的一系列方法。所以,String的本質是基於字符數組。

深入理解String,需要重點掌握以下幾點:
**1、String是不可變字符串
2、所有對String的修改都會返回新String
3、==和equal的區別**

且看部分關鍵源碼

/**
 *這段註釋對理解String非常重要,請仔細琢磨
 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared. For example:
 * <p><blockquote><pre>
 *     String str = "abc";
 * </pre></blockquote><p>
 * is equivalent to:
 * <p><blockquote><pre>
 *     char data[] = {'a', 'b', 'c'};
 *     String str = new String(data);
 * </pre></blockquote><p> 
 * */
 //**final修飾String,String不可被繼承,保證不可變性**
 public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /**
     這是一個字符數組,String的所有方法都是基於該字符數組
     如何保證String字符串不可變
     **-用private修飾value,使得value不可被外部訪問
     -用final修飾value, 不允許value指向另一個地址
     -所有String方法不改變value**
     以上三個因素保證了String字符串不可變
    */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    public String() {
        this.value = new char[0];
    }

    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

String不可變的特性,使得String字符串可被共享:
通過共享字符串,相同的字符串,不需額外分配內存空間,減少內存開銷,也有利於GC高效運行。

//代碼片段
String str = "abc";//會在常量池創建"abc"
String sharedStr = "abc";//常量池已存在"abc",不需要重新分配內存,直接引用常量池
System.out.println(str == sharedStr);//true,引用常量池同一個字符串

所有對String的修改都會返回新String:
由於String字符串是不可變的。所有對String的修改,會給新String分配內存空間,並且將該String拷貝到新String。

//代碼片段
String str = "hi,小佳";
String str1 = "my name is ben";
String newStr = str + str1;//爲newStr重新分配內存,分別將str和str1拷貝到newStr
System.out.println(str == newStr);//false,字符串內存首地址不相同

==和equals的區別:
以下是==和equals的測試案例,務必研究一番:

/**
*** == 比較兩個字符串首地址是否相等**
*/
String str = "str是字符串首地址";//str實際存儲的是字符串內存首地址
String sameStr = str;//sameStr、str指向同一個內存地址
String diffStr = "diffStr是字符串首地址,我擁有自己的內存空間";
System.out.println(str == sameStr);//true,字符串內存首地址相同
System.out.println(str == diffStr);//false,字符串內存首地址不相同

/**
 *下面是equals源碼
 ***equals:只要兩個字符串的內存首地址相等 或者 
 *字符串內容相等,equals返回true;否則,返回false。**
 *
 *String重寫了equals方法,且看equals源碼
 */
   public boolean equals(Object anObject) {
        //判斷內存首地址是否相等
        if (this == anObject) {
            return true;
        }
        //判斷字符串內容是否相等
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

//測試案例
String str = "hi,小佳";
String sameStr = "hi,小佳";
String diffStr = new String( "hi,小佳");//只要new一個String,都會給該String分配新的地址空間
System.out.println(str == diffStr);//false,字符串內存首地址不相同
System.out.println(str == sameStr);//true,字符串內存首地址相同
System.out.println(str.equals(diffStr));//true,字符串內容相等
System.out.println(str.equals(sameStr));//true,字符串內存首地址不相同

==和equals的區別總結:
給定兩個String對象 str1和str2,如果str1==str2爲true,那麼str1.equals(str2)必定爲true。

總結
String是Java的基礎,也是Java中最爲常用、最爲重要的一個類型,深入理解String,爲後續Java高級編程夯實基礎!

如果希望進一步理解String,推薦直接看源碼,建議重點閱讀這幾個函數:hashCode(String的哈希算法,值得研究), toString(String重寫了這個方法),getBytes(重點了解,此函數設計的編碼知識),subString(這個方法比較常用),split。

如果上面這些知識還滿足不了你的話,可以繼續深入學習StringBuilder,StringBuffer。需要掌握如下兩個知識點:
1. String,StringBuilder,StringBuffer區別(理解這三個類的區別,非常重要!)
2. StringBuilder,StringBuffer的應用場景

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章