次のコードを検討してください。
String first = "abc"; 
String second = new String("abc");
newキーワードを使用すると、Java はabc String再度作成しますよね? Stringこれは通常のヒープまたはプールに格納されますか? プールStringで終わるのは何秒ですか?String
次のコードを検討してください。
String first = "abc"; 
String second = new String("abc");
newキーワードを使用すると、Java はabc String再度作成しますよね? Stringこれは通常のヒープまたはプールに格納されますか? プールStringで終わるのは何秒ですか?String
newキーワードを使用すると、新しいStringオブジェクトが作成されます。オブジェクトは常にヒープ上にあることに注意してください。文字列プールは、ヒープとは別のメモリ領域ではありません。
文字列プールはキャッシュのようなものです。これを行う場合:
String s = "abc";
String p = "abc";
Stringその場合、Java コンパイラは 1 つのオブジェクトだけを作成するほどスマートでありs、p両方が同じ String オブジェクトを参照します。これを行う場合:
String s = new String("abc");
次にString、リテラルを表すプール内に 1 つのオブジェクトが存在し、プール内ではなく、プールされたオブジェクトのコンテンツのコピーを含む"abc"別のオブジェクトが存在します。Stringは Java では不変であるためString、これを行っても何も得られません。呼び出しnew String("literal")は Java ではまったく意味がなく、不必要に非効率的です。
オブジェクトintern()を呼び出すことができることに注意してください。Stringこれにより、Stringオブジェクトがまだ存在しない場合はプールに配置され、プールされた文字列への参照が返されます。(既にプールにある場合は、既に存在するオブジェクトへの参照を返すだけです)。詳細については、そのメソッドの API ドキュメントを参照してください。
文字列のインターン(ウィキペディア)も参照してください。
bytecodeでは、最初の割り当ては次のとおりです。
コード: 0: ldc #2; //文字列abc 2: アストア_1
一方、2番目は次のとおりです。
3: 新しい #3; //クラス java/lang/String 6: 複製 7: ldc #2; //文字列abc 9: 特殊呼び出し #4; //メソッド java/lang/String."":(Ljava/lang/String;)V
したがって、最初はプール (位置 #2) にあり、2 番目はヒープに格納されます。
編集
CONSTANT_String_info インデックスを U2 (16 ビット、符号なし) として格納するため、プールには最大で参照を含めることができ2**16ます65535。ここで気になる場合は、 JVM の制限を増やしてください。
コードが文字列リテラルを作成するたびに
例えば:
String str="Hello"; (string literal) 
JVM は最初に文字列リテラル プールをチェックします。文字列がプールに既に存在する場合は、プールされたインスタンスへの参照が返されます。文字列がプールに存在しない場合、新しい String オブジェクトがインスタンス化され、プールに配置されます。文字列は不変であり、データの破損を恐れずに共有できるため、Java はこの最適化を行うことができます。
new String(foo) を使用する必要があるのは、== を壊したいときだけです。これは奇妙なケースです。
String mystring;
{
   String source = getSomeHeinouslyLargeString();
   mystring = new String(source.substring(1,3));
}