JDK 1.4/1.5 中 String 核心欄位:
private final char value[]; // 字元陣列
private final int offset; // 起始索引
private final int count; // 字元長度
建構子 String(String original) 會嘗試共享底層 char[]:若原陣列長度大於實際內容,複製;否則直接引用同一陣列。
原始 equals(Object anObject) 邏輯:
this == anObject → true缺口:未檢查 value[] 與 offset 是否完全相同。若兩個 String 共享同一 char[] 且偏移/長度相同,理應直接回傳 true。
public boolean equals(Object anObject) {
if (this == anObject) return true;
if (anObject instanceof String) {
String another = (String) anObject;
int n = count;
if (n == another.count) {
char v1[] = value;
char v2[] = another.value;
int i = offset;
int j = another.offset;
// === 新增:陣列引用與偏移皆同 → 內容必同 ===
if (i == j && v1 == v2) return true;
while (n-- != 0) {
if (v1[i++] != v2[j++]) return false;
}
return true;
}
}
return false;
}
substring()、new String(existing)、字面常量池複用等產生共享陣列的情況。equals 合約。substring 已改為複製陣列,避免記憶體洩漏,共享機會大減。value 為 package-private,子類或同包類可能竄改陣列內容 (雖 String 為 final),引入參考比對需極度確信不可變性。this == anObject 涵蓋最常見的同一物件比對;字面常量編譯期已合併。此優化在早期 JDK 架構下合理且有效,展現了深入理解類別內部實現的價值。現代開發中,若有大量長字串比對需求,可考慮:
intern() 進入常量池,轉為參考比對。CharSequence 實現攜帶雜湊碼快速判斷。