String類
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{}
一旦一個String對象被創建,包含在這個對象中的字符序列是不可改變的,包括該類後續的所有方法都是不能修改該對象的,直至該對象被銷燬,這是我們需要特別注意的(該類的一些方法看似改變了字符串,其實內部都是創建一個新的字符串)
成員變量
/**用來存儲字符串 */
private final char value[];
/** 緩存字符串的哈希碼 */
private int hash; // Default to 0
/** 實現序列化的標識 */
private static final long serialVersionUID = -6849794470754667710L;
一個 String 字符串實際上是一個 char 數組。
構造方法
String str1 = "abc";
String str2 = new String("abc");
String str3 = new String(new char[]{'a','b','c'});
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 類重寫了equals方法,比較的是組成字符串的每一個字符是否相同,如果都相同則返回true,否則返回false
hashCode()
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
這裏有一個奇怪的數字31,網上查了一下,有以下兩點原因:
第一,31是一個不大不小的質數,是作爲hashCode乘子的優選質數之一。另外一下相近的質數,比如37、41、43等等,也都是不錯的選擇,那麼爲啥偏偏選中了31呢,請看第二個原因。
第二,31可以被JVM優化,31 * i = (i<<5) - i.。
charAt()
public char charAt(int index) {
// 如果傳入的索引大於字符串的長度或者小於0,直接拋出索引越界異常
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
通過傳入的索引(數組下標),返回指定索引的單個字符。
compareTo()
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;
}
按字母順序比較兩個字符串,是基於字符串中每個字符的Unicode值。當兩個字符串某個位置的字符不同時,返回的是這一位置的字符Unicode值之差,當兩個字符串相同時,返回兩個字符串長度之差。
compareToIgnoreCase() 方法在 compareTo 方法的基礎上忽略大小寫,我們知道大寫字母是比小寫字母的Unicode值小32的,底層實現是先都轉換成大寫比較,然後都轉換成小寫進行比較。
concat()
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
首先判斷要拼接的字符串長度是否爲0,如果爲0,則直接返回原字符串。如果部位0,則通過Arrays工具類(後面會詳細介紹這個工具類)的copyOf方法創建一個新的字符數組,長度爲原字符串之和,情面填充原字符串,後面爲空。接着在通過getChars方法將要拼接的字符串放入新字符串後面爲空的位置。
indexOf(int ch, int fromIndex)
public int indexOf(int ch, int fromIndex) {
final int max = value.length; // max等於字符的長度
if (fromIndex < 0) { // 指定索引的位置如果小於0,默認從0開始搜索
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
// 如果指定索引值大於等於字符的長度(因爲是數組,下標最多隻能是max-1),直接返回-1
return -1;
}
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// 一個char佔用兩個字節,如果ch小於2的16次方(65536),絕大多數字符都在此範圍內
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
for (int i = fromIndex; i < max; i++) { // for循環依次判斷字符串每個字符是否和指定字符相等
if (value[i] == ch) {
return i; // 存在相等的字符,返回第一次出現該字符的索引位置,並終止循環
}
}
return -1; //不存在相等的字符,返回-1
} else { // 當字符大於65536時,處理的少數情況,該方法會首先判斷是否是有效字符,然後依次進行比較
return indexOfSupplementary(ch, fromIndex);
}
}
indexOf(int ch),參數 ch 其實是字符的 Unicode 值,這裏也可以放單個字符(默認轉成int),作用是返回指定字符第一次出現的此字符串中的索引。其內部是調用 indexOf(int ch, int fromIndex),只不過這裏的 fromIndex =0 ,因爲是從 0 開始搜索;而 indexOf(int ch, int fromIndex) 作用也是返回首次出現的此字符串內的索引,但是從指定索引處開始搜索。