Javaでは、String オブジェクトは不変 です。つまり、一度作成されたら、その内容は決して変わりません。String を修正しているように見える操作は、実際には新しい String を作成しています。効率的に繰り返し修正するには、StringBuilder を使用します。
なぜ重要なのか
;
s.concat();
System.out.println(s);
s = s + ;
concat、toUpperCase、replace、substring などのメソッドはすべて新しい String オブジェクトを返します。元の String は決して修正されません。
✓ Thread safety — immutable objects are safe to share across threads (no locking)
✓ String pool — identical string literals can be SHARED/reused (memory savings)
✓ Hashing/keys — safe as HashMap keys (hashCode can be cached, never changes)
✓ Security — strings used for filenames, URLs, credentials can't be altered
after a security check
不変性により、String は本質的にスレッドセーフになり、JVM は String pool を通じてリテラルをインターン(共有)でき、String をマップキーとして安全にします(ハッシュ値は変わりません)。
// ❌ creates a NEW string object on EVERY iteration — O(n²), wasteful
String result = "";
for (int i = 0; i < 10000; i++) {
result += i; // each += allocates a whole new string
}
各 += は新しい String を作成し(以前のすべてのコンテンツをコピー)、ループ内で文字列を構築することは二次時間であり、多くのガベージを生成します。
// ✅ StringBuilder mutates an internal buffer — O(n), efficient
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i); // modifies the buffer in place, no new objects
}
String result = sb.toString(); // convert to a String once, at the end
StringBuilder は可変の文字列シーケンスです。append/insert/delete は新しいオブジェクトを作成せずに内部バッファを修正し、ループベースの構築を効率的にします。(StringBuffer はスレッドセーフですが、より遅い変種です。)
String の不変性は Java の重要な特性であり、重要な結果があります。スレッドセーフティを提供し、メモリセービングの string pool を可能にし、String をマップキーとしてセキュリティコンテキストで安全にします。しかし、これはループ内での単純な文字列連結が真のパフォーマンスの落とし穴(O(n²)、過剰なガベージ)であることを意味します。
繰り返し修正するために StringBuilder を使用することを知ることは、不変性を理解することから直接得られる実務的な必要性です。
この組み合わせ — String が不変である理由(安全性、共有、ハッシング)と、StringBuilder に切り替えるタイミング(ループ連結)— は、インタビューの一般的なトピックであり、現実世界での頻繁なパフォーマンス修正です。