1. 程式人生 > >JSK1.8 String類部分原始碼分析

JSK1.8 String類部分原始碼分析

本文基於JDK1.8中的String類,看原始碼時無意發現String類中幾個比較有意思的地方,特此記錄下。

String類的兩個重要屬性,final的字元陣列和int的hash值,還有序列化相關的兩個欄位,這裡不寫;

final char value[]初始化後將是不可以變的,與String類的final關鍵字相呼應,保證的字串的不變性;特別是在初始化字串物件時,如果常量池中存在該字串,可以將value直接指向常量池中的字串,這樣既節省記憶體又方便,同時由於是final型別,也沒有多執行緒併發問題。

private int hash在JVM中,int型別預設初始化為0,在未調hashCode時hashCode一直是0,只有在調一次時還會生成。

    /** The value is used for character storage. */
    private final char value[];        

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

hashCode()方法:

    // hashCode生成規則,s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {    // 只有第一次呼叫時才會生成一個hashCode並賦值
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

compareTo()方法, 這個方法有意思的地方在while迴圈中,return c1 - c2,這種寫法,直接通過字元的ASCII碼相減得到一個int值,進行返回,高下立判斷:

public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2; 
  }

構造方法String(String original),通過String構造自身的構造方法,省事,不需要通過Arrays.copyOf重新做一份copy,直接應用之前String類的value和賦值hash值,反正是final的:

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

intern()方法,這是個本地方法,通過此方法可以將字串陣列放到方法區(不同JDK版本方法區叫法位置可能不一樣,這也是需要研究的),合適的時候呼叫intern方法,可以減少建立物件的個數,減少記憶體開銷(共用了記憶體啊)。

 public native String intern();