1. 程式人生 > 實用技巧 >String-重要方法的原始碼解析

String-重要方法的原始碼解析

1. String的底層實現

String 內部實際儲存結構為 char 陣列,原始碼如下:

public final class String

    implements java.io.Serializable, Comparable\<String\>, CharSequence {

    // 用於儲存字串的值

    private final char value[];

    // 快取字串的 hash code

    private int hash; // Default to 0

    // ......其他內容

}

String 原始碼中包含下面幾個重要的方法。


2. 多構造方法

String 字串有以下 4 個重要的構造方法:

// String 為引數的構造方法

public String(String original) {

    this.value = original.value;

    this.hash = original.hash;

}

// char[] 為引數構造方法

public String(char value[]) {

    this.value = Arrays.copyOf(value, value.length);

}

// StringBuffer 為引數的構造方法

public String(StringBuffer buffer) {

    synchronized(buffer) {

        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());

    }

}

// StringBuilder 為引數的構造方法

public String(StringBuilder builder) {

    this.value = Arrays.copyOf(builder.getValue(), builder.length());

}

其中,比較容易被我們忽略的是以 StringBuffer 和 StringBuilder
為引數的建構函式,因為這三種資料型別,我們通常都是單獨使用的,所以這個小細節我們需要特別留意一下。


3. equals() 比較兩個字串是否相等

原始碼如下:

public boolean equals(Object anObject) {

    // 物件引用相同直接返回 true

    if (this == anObject) {

        return true;

    }

    // 判斷需要對比的值是否為 String 型別,如果不是則直接返回 false

    if (anObject instanceof String) {

        String anotherString = (String)anObject;

        int n = value.length;

        if (n == anotherString.value.length) {

            // 把兩個字串都轉換為 char 陣列對比

            char v1[] = value;

            char v2[] = anotherString.value;

            int i = 0;

            // 迴圈比對兩個字串的每一個字元

            while (n-- != 0) {

                // 如果其中有一個字元不相等就 true false,否則繼續對比

                if (v1[i] != v2[i])

                    return false;

                i++;

            }

            return true;

        }

    }

    return false;

}

String 型別重寫了 Object 中的 equals() 方法,equals() 方法需要傳遞一個 Object 型別的引數值,在比較時會先通過
instanceof 判斷是否為 String 型別,如果不是則會直接返回 false,instanceof 的使用如下:

Object oString = "123";

Object oInt = 123;

System.out.println(oString instanceof String); // 返回 true

System.out.println(oInt instanceof String); // 返回 false

當判斷引數為
String 型別之後,會迴圈對比兩個字串中的每一個字元,當所有字元都相等時返回 true,否則則返回
false。

還有一個和 equals() 比較類似的方法
equalsIgnoreCase(),它是用於忽略字串的大小寫之後進行字串對比。


4. compareTo() 比較兩個字串

compareTo() 方法用於比較兩個字串,返回的結果為 int 型別的值,原始碼如下:

public int compareTo(String anotherString) {

    int len1 = value.length;

    int len2 = anotherString.value.length;

    // 獲取到兩個字串長度最短的那個 int 值

    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;

}

從原始碼中可以看出,compareTo() 方法會迴圈對比所有的字元,當兩個字串中有任意一個字元不相同時,則
return char1-char2。比如,兩個字串分別儲存的是 1 和 2,返回的值是
-1;如果儲存的是 1 和 1,則返回的值是 0 ,如果儲存的是 2 和 1,則返回的值是 1。

還有一個和 compareTo() 比較類似的方法
compareToIgnoreCase(),用於忽略大小寫後比較兩個字串。

可以看出 compareTo() 方法和 equals() 方法都是用於比較兩個字串的,但它們有兩點不同:

  • equals() 可以接收一個 Object 型別的引數,而
    compareTo() 只能接收一個 String 型別的引數;

  • equals() 返回值為 Boolean,而 compareTo() 的返回值則為 int。

它們都可以用於兩個字串的比較,當 equals() 方法返回 true 時,或者是 compareTo() 方法返回
0 時,則表示兩個字串完全相同。


5. 其他重要方法

方法名 作用
indexOf() 查詢字串首次出現的下標位置
lastIndexOf() 查詢字串最後出現的下標位置
contains() 查詢字串中是否包含另一個字串
toLowerCase() 把字串全部轉換成小寫
toUpperCase() 把字串全部轉換成大寫
length() 查詢字串的長度
trim() 去掉字串首尾空格
replace() 替換字串中的某些字元
split() 把字串分割並返回字串陣列
join() 把字串陣列轉為字串