71

次のコードを検討してください。

String first = "abc"; 
String second = new String("abc");

newキーワードを使用すると、Java はabc String再度作成しますよね? Stringこれは通常のヒープまたはプールに格納されますか? プールStringで終わるのは何秒ですか?String

4

7 に答える 7

97

newキーワードを使用すると、新しいStringオブジェクトが作成されます。オブジェクトは常にヒープ上にあることに注意してください。文字列プールは、ヒープとは別のメモリ領域ではありません。

文字列プールはキャッシュのようなものです。これを行う場合:

String s = "abc";
String p = "abc";

Stringその場合、Java コンパイラは 1 つのオブジェクトだけを作成するほどスマートでありsp両方が同じ String オブジェクトを参照します。これを行う場合:

String s = new String("abc");

次にString、リテラルを表すプール内に 1 つのオブジェクトが存在し、プール内ではなく、プールされたオブジェクトのコンテンツのコピーを含む"abc"別のオブジェクトが存在します。Stringは Java では不変であるためString、これを行っても何も得られません。呼び出しnew String("literal")は Java ではまったく意味がなく、不必要に非効率的です。

オブジェクトintern()を呼び出すことができることに注意してください。Stringこれにより、Stringオブジェクトがまだ存在しない場合はプールに配置され、プールされた文字列への参照が返されます。(既にプールにある場合は、既に存在するオブジェクトへの参照を返すだけです)。詳細については、そのメソッドの API ドキュメントを参照してください。

文字列のインターン(ウィキペディア)も参照してください。

于 2009-12-10T15:52:52.330 に答える
12

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 の制限を増やしてください。

于 2009-12-10T15:53:46.120 に答える
7

コードが文字列リテラルを作成するたびに

例えば:

String str="Hello"; (string literal) 

JVM は最初に文字列リテラル プールをチェックします。文字列がプールに既に存在する場合は、プールされたインスタンスへの参照が返されます。文字列がプールに存在しない場合、新しい String オブジェクトがインスタンス化され、プールに配置されます。文字列は不変であり、データの破損を恐れずに共有できるため、Java はこの最適化を行うことができます。

于 2009-12-10T17:06:05.467 に答える
2

new String(foo) を使用する必要があるのは、== を壊したいときだけです。これは奇妙なケースです。

String mystring;
{
   String source = getSomeHeinouslyLargeString();
   mystring = new String(source.substring(1,3));
}
于 2009-12-12T05:44:27.553 に答える