【Java】文字列リテラルが文字列定数プール(SCP)に格納される理由をわかりやすく解説
JavaでStringオブジェクトを生成する方法は、主に以下の2つがあります。
- new演算子を使用する方法
String str = new String("Tutorials Point");- 文字列リテラルを使用する方法
String str = "Tutorials Point";
文字列定数プール(SCP)とは
Javaでnew String()を呼び出すたびに、ヒープメモリ上には新しいオブジェクトが作成されます。一方、文字列リテラルは「文字列定数プール(String Constant Pool:SCP)」と呼ばれる特別な領域に格納されます。
JVMはメモリを効率的に管理するためにこのSCPを採用しています。Stringは他のJavaオブジェクトと異なり不変(イミュータブル)であるため、ヒープ領域で個別に管理する代わりに、専用の文字列定数プールを設けることで、重複する文字列オブジェクトの生成を防ぎ、メモリ使用量を抑えています。
文字列定数プールの重要な特徴は、プール内に同一の文字列定数がすでに存在する場合、新たにStringオブジェクトを作成せず、既存の参照を再利用するという点です。これにより、同じ内容の文字列を何度使っても、メモリ上には1つのインスタンスしか保持されません。
サンプルコード
public class SCPDemo {
public static void main(String args[]) {
String s1 = "Tutorials Point";
String s2 = "Tutorials Point";
System.out.println("s1とs2(文字列リテラル):");
System.out.println(s1 == s2);
String s3 = new String("Tutorials Point");
String s4 = new String("Tutorials Point");
System.out.println("s3とs4(new演算子使用):");
System.out.println(s3 == s4);
}
}実行結果
s1とs2(文字列リテラル):
true
s3とs4(new演算子使用):
false
結果の解説
s1とs2は文字列リテラルとして宣言されているため、どちらもSCP内の同じオブジェクトを参照します。そのため、参照を比較する==演算子の結果はtrueになります。
一方、s3とs4はnew演算子で生成しているため、呼び出しごとにヒープメモリ上へ別々の新しいオブジェクトが作成されます。したがって、==による比較結果はfalseとなります。
なお、文字列の内容そのものを比較したい場合はequals()メソッドを使用します。また、intern()メソッドを利用すれば、newで生成したStringオブジェクトをSCP内の同等のリテラル参照に置き換えることも可能です。
-
JavaのStringIndexOutOfBoundsExceptionとは?発生原因と対処法をわかりやすく解説
StringIndexOutOfBoundsExceptionとはJavaにおいて、文字列(String)は一連の文字を格納するために使用され、オブジェクトとして扱われます。文字列は、java.langパッケージに含まれるStringクラスによって表現されます。文字列の作成方法は主に2つあります。1つは他のオブジェクトと同様にnewキーワードを使用する方法、もう1つはプリミティブ型のようにリテラルを直接代入する方法です。String stringObject = new String(Hello how are you); String stringLiteral = Welcome to T
-
なぜJavaのStringクラスは不変(イミュータブル)かつfinalとして設計されているのか?
Stringが不変(イミュータブル)であるとは?JavaにおいてStringクラスが「不変(immutable)」であるということは、オブジェクトそのものの状態を後から変更できないことを意味します。ただし、オブジェクトを参照する変数(参照先)は別のオブジェクトに差し替えることが可能です。また、Stringクラスがfinalとして宣言されているのは、他のクラスによる継承を禁止し、この不変性を破壊されるのを防ぐためです。もし継承が許されていれば、サブクラスで挙動を上書きされ、Stringの安全性が損なわれてしまいます。では、なぜJavaの設計者はStringを不変にしたのでしょうか?主な理由は以下