首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Java String 構造器中 originalValue.length > size 的深度解析

     編輯:C++ 入門

現象觀察

在 JDK 6 `String(String original)` 構造器中發現判斷:

public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
    if (originalValue.length > size) {  // 為什麼會發生?
        int off = original.offset;
        v = Arrays.copyOfRange(originalValue, off, off + size);
    } else {
        v = originalValue;
    }
    this.offset = 0;
    this.count = size;
    this.value = v;
}

根因分析:substring 共享底層字符數組

JDK 6 中 `String` 使用 char[] value + int offset + int count 表示字符串,substring 不複製數組,直接共享:

public String substring(int beginIndex, int endIndex) {
    // ... 邊界檢查 ...
    return new String(offset + beginIndex, endIndex - beginIndex, value);
}

// 包私有構造器,共享 value 數組
String(int offset, int count, char[] value) {
    this.value = value;
    this.offset = offset;
    this.count = count;
}

場景重現

String s1 = "hello world";      // value.length=11, offset=0, count=11
String s2 = s1.substring(6);    // value=同一數組, offset=6, count=5 ("world")
String s3 = new String(s2);     // 調用 String(String original)

// 在構造器中:
// originalValue.length = 11 (共享的原始數組長度)
// size = original.count = 5 (s2 的邏輯長度)
// 11 > 5 → 進入複製分支
// off = 6, copyOfRange(value, 6, 11) → 新數組 ['w','o','r','l','d']

為什麼要這樣設計?

內存洩漏風險演示

// 1MB 的大字符串
String huge = new String(new char[1024*1024]);  // 1MB char[]
// 只取前 10 個字符
String tiny = huge.substring(0, 10);  // 共享 1MB 數組!
// huge 失去引用,但 tiny 仍引用 1MB 數組 → 1MB 內存無法釋放
// 若不複製,tiny 會導致巨大內存洩漏

// String(String) 構造器複製後:
String safe = new String(tiny);  // 複製 10 字符到新數組,1MB 可被 GC

JDK 7/8 的變化

JDK 7 移除了 `offset` 和 `count` 字段,`substring` 總是複製數組:

// JDK 7+
public String substring(int beginIndex, int endIndex) {
    int subLen = endIndex - beginIndex;
    return new String(Arrays.copyOfRange(value, beginIndex, endIndex));
}

優點:簡單、無洩漏風險。缺點:`substring` 從 O(1) 變為 O(n)。

總結

  • originalValue.length > size 發生在調用 `new String(substring)` 時。
  • 原因:`substring` 共享底層數組並使用 `offset/count` 定義邏輯視圖,導致物理數組長度 > 邏輯長度。
  • 構造器檢測到此情況,複製有效片段到新數組,斷開對大數組的引用,防止內存洩漏。
  • 這是 JDK 6 為平衡 `substring` 性能(O(1))與內存安全所做的妥協設計。
  • 現代 JDK (7+) 選擇簡單可靠:`substring` 永遠複製,犧牲性能換取無洩漏保證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
情況處理原因
originalValue.length == size直接共享數組原字符串無偏移、無截取,數組恰好滿,安全共享
originalValue.length > size複製相關片段到新數組原數組被共享且有未使用部分(offset>0 或 count