1.String
1.1類的定義
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
String類在定義時候使用final關鍵字進行修飾,限制了這個類無法被繼承,里面的方法也無法被重寫。
同時它還實現了Serializable接口、Comparable接口,以及CharSequence接口三個接口:
- Serializable:序列化接口,如果允許對象被序列化需要實現該類。
- Comparable:比較對象大小的接口,用來定義對象之間如何進行大小的比較。
- CharSequence:字符序列接口,相比String類,它是一個更為廣泛的可讀可寫字符序列,而String類是只可讀的。
1.2類的成員變
/** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0
String類中常用的兩個成員變量value、hash。
- value:字符類型的數組,用來存放我們所保存的字符串,每一個字符串都會被拆開作為字符來進行存儲。
- hash:對應字符串的hash值。
1.3常用方法
length():返回value數組的長度。
public int length() { return value.length; }
indexOf(str):獲取在字符串中某個字符串的起始位置。這里其實也是用的遍歷,從指定的開始位置起,一直遍歷直到找到目標字符串,或者直到源字符串的最后一位(其實是最后一位減去目標字符串的長度)。
public int indexOf(String str) { return indexOf(str, 0); } public int indexOf(String str, int fromIndex) { return indexOf(value, 0, value.length, str.value, 0, str.value.length, fromIndex); } static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { while (++i <= max && source[i] != first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; }
compareTo(str):比較兩個字符串的大小,采用的是逐個字符來進行比較(比較ASCII碼)。
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; }
1.4總結
String類是一個可序列化,可按照字符大小進行排序,不可繼承、只讀的字符序列類。
2.StringBuilder
2.1類定義
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
StringBuilder和String的定義類似,同樣被final關鍵字修飾,限定了無法被繼承,同時繼承Serializable和CharSequence兩個接口。
同時最它多繼承了一個抽象類AblstractStringBuilder。
2.2成員變量
在StringBuilder中沒有再定義其他的成員變量,所使用的底層存放數據的變量來自於父類AbstractStringBuilder。
在AbstractStringBuilder中,定義了三個成員變量
char[] value; int count; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
- value:字符數組,用來存放傳入的字符串。
- count:int類型,記錄value中存放元素的長度。
- MAX_ARRAY_SIZE:靜態常量,代指允許value數組的最大長度。
2.3常用方法
append(str):相比String只讀的屬性,StringBuilder允許我們對其進行寫操作。但是由於底層存放數據的是一個數組,因此每次都需要進行一個擴容的判斷。如果count+入參字符串的長度大於當前數組value的長度,就需要進行擴容,每次擴容后的數組長度=原長度*2+2。
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; }
2.4總結
StringBuilder補充了String只能讀不能寫的屬性,采用對數組擴容的操作,允許程序員對String類型來進行寫操作。
3.StringBuffer
3.1類定義
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
StringBuffer的定義與StringBuilder類似,同樣繼承了AbstractStringBuilder抽象類,實現了Serializable和CharSequence接口。
3.2成員變量
StringBuffer的成員變量和StringBuilder一樣,同樣適用在AbstractStringBuilder中定義好的字符類型數組value和int類型count。
3.3常用方法
append(str):與StringBuilder類似的,兩個類都是通過調用AbstractStringBuilder中的append(str)方法來添加字符串。
區別在於StringBuffer的方法定義上多了一個關鍵字:Synchronized。通過這個關鍵字,來保證我們對字符串的寫操作的線程安全。
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
toString():和StringBuilder的toString()方法不一樣,這里在StringBuffer中就已經完成了對字符數組的復制,如果連續調用toString()方法,實際返回的都是同一個String對象。而在StringBuilder中,由於數組的復制是發生在String類里面,因此每次調用后返回的都是不同的String對象。
@Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
3.4總結
StringBuffer在Stringbuilder實現了字符串寫操作的基礎上,又添加了對它的線程安全方面的維護,通過查看源碼,可見都是通過在方法上添加synchronized關鍵字來顯示的。這樣雖然可以保證線程安全,但是也在一定程度上,舍棄了部分性能。不過在jdk1.5之后對鎖的優化,新增了偏向鎖、輕量級鎖后,如果我們對字符串的寫操作不涉及多線程的時候,StringBuffer和StringBuilder的資源損耗是幾乎類似的。但如果一旦涉及多線程,StringBuffer則能更好的保障我們的線程安全。
4.總結
String類是java中定義用來保存一個字符序列的對象,但是對它的操作只有讀,而沒有寫。所有的寫操作實際都是返回了一個新的字符串對象。
StringBuilder類在String類的基礎上,增加了對字符序列的寫操作,采用底層數組擴容的方式,來允許添加新的字符串,或刪除里面原有的字符串。
StringBuffer類由在StringBuilder類的基礎上,既滿足了對字符序列的寫操作,又保證了操作的線程安全。因此在實際情況下,優先推薦使用StringBuffer類。
成員變量
String類型