Stringクラスは特別扱い!?”文字列”で作れるStringインスタンス

Java Silver

Stringインスタンスの生成方法

通常、インスタンスはnew演算子を使用して生成します。

Object obj = new Object();

しかし、Stringインスタンスは「””」で文字列を囲うだけでStringインスタンスを生成することができます。

String str = "SAMPLE";

もちろん、new演算子を使用してインスタンス生成することも可能です。

String str = new String("SAMPLE");

コンスタントプールという仕組み

「”文字列”」という記述でStringインスタンス(文字列リテラル)を生成した場合、

「コンスタントプール」というメモリ領域にStringインスタンス(文字列リテラル)が生成されます。

プログラム中ではStringインスタンス(文字列リテラル)が多く出現しますが、その度にメモリ領域にStringインスタンス(文字列リテラル)を生成していると、メモリ領域は圧迫され、リソースの負荷が高まるばかりです。

そのため「”文字列”」という記述で生成されたStringインスタンス(文字列リテラル)は、通常のインスタンスが利用するメモリ空間とは別のメモリ空間(=コンスタントプール)に作成されることになります。

そして「”文字列”」の記述によって生成されたStringインスタンス(文字列リテラル)が既にコンスタントプールに存在する場合、そのStringインスタンス(文字列リテラル)への参照が再利用されることになります。

このように、コンスタントプールを利用し無駄なメモリ消費を抑えることで、リソースを効率的に使うことができます。

例題

それでは、上記を踏まえて試験問題を解いてみましょう。

以下コードを実行した際、出力結果はどうなるでしょう。

String a = "sample";
String b = "sample";
String c = new String("sample");

System.out.println( a == b );
System.out.println( a == c );
System.out.println( a.equals(b) );
System.out.println( a.equals(c) );

正解は以下の通りです。

以下コードを実行した際、出力結果はどうなるでしょう。

String a = "sample";
String b = "sample";
String c = new String("sample");

System.out.println( a == b );
⇒ true
コンスタントプールのStringインスタンス(文字列リテラル)への参照が再利用されるので、aとbが保持しているインスタンスのアドレス値は同じになります。

System.out.println( a == c );
⇒ false
new演算子によってStringインスタンスを生成した場合、コンスタントプールは利用されません。よって、aとcが保持しているインスタンスのアドレス値は異なります。

System.out.println( a.equals(b) );
⇒ true
Stringクラスのequalsメソッドは「同じ文字列リテラルかどうか」で判定を行います。
aとbが参照しているインスタンスは同じ文字列リテラル「sample」を保持しているため、trueが返されます。

System.out.println( a.equals(c) );
⇒ true
Stringクラスのequalsメソッドは「同じ文字列リテラルかどうか」で判定を行います。
aとcが保持するインスタンスのアドレス値は異なりますが、
参照するインスタンスが保持する文字列リテラルは「sample」で同じであるため、trueが返されます。

まとめ

  • 「”文字列”」の記述でStringインスタンスを生成すると、コンスタントプールにインスタンスが生成される
  • コンスタントプールにStringインスタンスが生成される場合、同じ文字列リテラルを持つStringインスタンスが既に存在するなら、そのStringインスタンスが再利用される
  • new演算子によってStringインスタンスを生成した場合、コンスタントプールは利用されない
  • Stringクラスのequalsメソッドは「同じ文字列リテラルかどうか」で判定を行う

コメント

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