PR

【Java】String.intern()とStringPoolの基本を1分で

Java

intern()は「文字列プールの中にその文字列があればそれを返し、なければ追加して返す」メソッドです。

Javaには同じ文字列が何度も使われることを想定して、メモリのムダをなくす工夫があります。それが「文字列プール(String Pool)」です。intern()メソッドは、このプールと関係しています。

スポンサーリンク

Javaの文字列リテラルと文字列プールとは?

Javaでは、文字列を "apple" のようにダブルクオーテーションで書いたものを文字列リテラルと呼びます。

参考 リテラルの基本概念

String s = "apple";

このように書かれた文字列は、文字列プール(String Pool)という特別な場所に自動で保存されます。文字列プールとは、同じ文字列を一度だけ保存しておく場所、そしてそれを使いまわす仕組みです。

つまり、同じ "apple" を何度使っても、同じ1つのインスタンスを共有することで、メモリの節約しよう!という考え方です。

new String()を使うと何が起こる?

次のようなコードを書いたとします。

String s = new String("apple");

このとき、"apple" というリテラルはプールに登録されますが、new String(...)新しいインスタンスをヒープ領域に作成します。つまり、↑のコードは内部で次の2つの処理が行われています:

  1. リテラル部分 "apple"
    ソースコード中の文字列リテラルは、クラスがロードされる際に自動的に文字列プールに登録されます。つまり、この時点で "apple" は既にプール内に存在することになります。
  2. new String("apple"):
    new String(...) は、プールにあるリテラル "apple" を元にしてヒープ上に新しい String オブジェクトを生成します。
    ※ この新たなオブジェクトはプールに登録されず、ヒープ上の独立した存在です。

比較するとこうなります:

String s1 = "apple";                  // プール上の"apple"
String s2 = new String("apple");     // ヒープ上の新しい"apple"

System.out.println(s1 == s2); // false(参照が異なる)

intern()の役割とは?

intern()メソッドを使うと、次のような動作をします:

「この文字列と同じ内容の文字列が文字列プールにあるかを確認し、あればそれを返す。なければプールに登録して返す

つまり、new String(...) のようにヒープに作られた文字列も、プールにある文字列と結びつけられるのです。

String s1 = "apple";
String s2 = new String("apple");
String s3 = s2.intern();

System.out.println(s1 == s2); // false(ヒープとプールで違う)
System.out.println(s1 == s3); // true(どちらもプール)
  1. リテラル "apple":
    クラスロード時に文字列プールに登録される(自動で管理される)。
  2. new String("apple"):
    ヒープ上に新しいオブジェクトを生成。内部で使われているリテラルはプールされているが、この新オブジェクト自体はプールには入りません。
  3. new String("apple").intern():
    プール内に既に "apple" があるので、その参照が返される(= リテラル "apple" と同じインスタンス)。

intern()を使うと何がうれしいの?

✅ メモリ効率が良くなる

同じ文字列を何度も使っている場合、それぞれが別のインスタンスだとメモリがムダになります。intern()を使えば1つにまとめられます。

✅ ==で比較できるようになる

Javaでは==は「中身」ではなく「参照(場所)」の比較です。intern()でプールに統一しておけば、中身が同じ文字列は同じ参照になるため、==で比較できるようになります。

タイトルとURLをコピーしました