String オブジェクトを直接作成する:
String s1 = "Hip Hop"
文字列オブジェクトを作成しますが、最初に JVM が文字列定数またはリテラル プールをチェックし、文字列が存在しない場合は、新しい文字列オブジェクト「ヒップ ジョップ」を作成し、参照がプールに保持されます。変数s1
も同じオブジェクトを参照します。さて、この後にステートメントを置くと:
String s2 = "Hip Hop"
JVM は最初に文字列定数プールをチェックします。文字列は既に存在するため、プールされたインスタンスへの参照が に返されs2
ます。
System.out.println(s1==s2) // comparing reference and it will print true
文字列は不変であり、データの破損を心配することなく共有できるため、Java はこの最適化を行うことができます。
new を使用して文字列オブジェクトを作成する
String s3 = new String("Hip Hop")
new
キーワードの場合、ヒープ メモリで String オブジェクトが作成されます。または、等しい文字列オブジェクトがプールに既に存在し、新しく作成されs3
たオブジェクトを参照します。
System.out.println(s3==s2) // two reference is different, will print false
演算子で作成された文字列オブジェクトは、文字列プールnew
内のオブジェクトを参照しませんが、文字列のメソッドを使用して作成できます。は、インターンされた String、つまり、グローバルなString リテラル プールにエントリを持つ String を返します。文字列がグローバル文字列リテラル プールにまだない場合は、プールに追加されます。intern()
java.lang.String.intern()
String s4 = s3.intern();
Systen.out.println(s4 == s2); // will print `true` because s4 is interned,
//it now have the same reference to "Hip Hop" as s2 or s1
しかし、試してください:
Systen.out.println(s4 == s3) // it will be false,
の参照として、s4
はプールされたインスタンスへの参照でs2
あり、 はヒープ メモリ内に作成されたオブジェクトを参照しています。s1
s3
文字列を作成するための new の使用:
OpenJDK 7、Update 6 より前では、JavaString.susbtring
メソッドに潜在的なメモリ リークがありました。substring
メソッドは、コピーを避けるために、char 配列全体への参照を保持する新しい String オブジェクトを構築します。したがって、たった 1 文字の文字列を持つ非常に大きな文字配列への参照を誤って保持してしまう可能性があります。の後に最小限の文字列が必要な場合はsubstring
、別の文字列を取得するコンストラクターを使用します。
String s2 = new String(s1.substring(0,1));
この問題は JDK 7 update 6 で解決されています。そのため、文字列リテラル プールメカニズム new
によって提供される利点を利用するために文字列を作成する必要がなくなりました。
参考:
- 文字列リテラル プール
- 部分文字列を使用するためのメモリリークを防ぐために new を使用する