6
class A { 

String s4 = "abc";

 static public void main(String[]args ) {

        String s1 = "abc";
        String s2 = "abc";
        String s3 = new String("abc");
        A o = new A();
        String s5 = new String("def");

        System.out.println("s1==s2 : " + (s1==s2));
        System.out.println("s1==s1.intern : " + (s1==s1.intern()));
        System.out.println("s1==s3 : " + (s1==s3));
        System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern()));
        System.out.println("s1==s4 : " + (s1==o.s4));
 }
} 

出力:

s1==s2 : true
s1==s1.intern : true
s1==s3 : false
s1.intern==s3.intern : true
s1==s4 : true

私の質問:

1.どうなり"String s1 = "abc"ますか?Stringオブジェクトは、文字列クラスのプールにインターン文字列として追加されていると思いますか?それはどこに置かれますか?「永続的な生成」または単にヒープ(文字列クラスインスタンスのデータメンバーとして)?

2.どうなり"String s2 = "abc"ますか?オブジェクトは作成されていないと思いますが、これはJava Intepreterがすべてのインターン文字列を検索する必要があることを意味しますか?これによりパフォーマンスの問題が発生しますか?

3.String s3 = new String("abc") インターン文字列を使用していないようです。なぜですか?

4.String s5 = new String("def")新しいインターン文字列を作成しますか?

4

4 に答える 4

5
  1. コンパイラは定数プールに"abc" の String オブジェクトを作成し、代入ステートメントのバイトコードでそれへの参照を生成します。

  2. (1) を参照してください。検索はありません。パフォーマンスの問題はありません。

  3. これは、実行時に新しい String オブジェクトを作成します。これは、'new' 演算子が行うことであり、新しいオブジェクトを作成するためです。

  4. はい、「def」の場合ですが、(3) により、実行時に新しい文字列も作成されます。

3 ~ 4 の String オブジェクトはインターンされません。

于 2012-05-20T09:58:21.000 に答える
3

1.「文字列 s1 = "abc"」の場合はどうなりますか?

コンパイル時に、リテラルの表現が、このコードを含むクラスのクラスファイルの「定数プール」部分に書き込まれます。

クラスがロードされると、クラスファイルの定数プール内の文字列リテラルの表現が読み取られ、そこから新しい String オブジェクトが作成されます。次に、この文字列がインターンされ、インターンされた文字列への参照がコードに「埋め込まれます」。

実行時に、以前に作成/インターンされた String への参照が に割り当てられs1ます。(このステートメントの実行時に文字列の作成やインターンは行われません。)

String オブジェクトは、インターンされた文字列としてクラス String のプールに追加されると思いますか?

はい。ただし、コードが実行されたときではありません。

それはどこに置かれていますか?「永続的な世代」または単なるヒープ (文字列クラス インスタンスのデータ メンバーとして)?

ヒープの permgen 領域に格納されます。(String クラスには静的フィールドはありません。JVM の文字列プールはネイティブ コードで実装されます。)

2.「文字列 s2 = "abc"」の場合はどうなりますか?

ロード時には何も起こりません。コンパイラがクラスファイルを作成するとき、リテラルの最初の使用に使用されたのと同じ定数プール エントリをリテラルに再利用しました。したがって、このステートメントで使用される文字列参照は、前のステートメントで使用されるものと同じです。

オブジェクトは作成されていないと思います。

正しい。

しかしこれは、Java インタプリタがインターンされたすべての文字列を検索する必要があるということでしょうか? これによりパフォーマンスの問題が発生しますか?

いいえ、いいえ。Java インタープリター (または JIT コンパイル済みコード) は、前のステートメントで作成または埋め込まれたものと同じ参照を使用します。

3. String s3 = new String("abc") はインターンされた文字列を使用していないようです。なぜですか?

それよりも複雑です。コンストラクター呼び出し、インターンされた文字列を使用してから、新しい文字列を作成し、インターンされた文字列の文字を新しい文字列の表現にコピーします。新しく作成された文字列が に割り当てられs3ます。

なんで?newは常に新しいオブジェクトを作成するように指定されており (JLS を参照)、Stringコンストラクターは文字をコピーするように指定されているためです。

4. String s5 = new String("def") は新しいインターン文字列を作成しますか?

新しいインターンされた文字列はロード時に作成され (「def」用)、実行時にインターンされた文字列のコピーである新しい String オブジェクトが作成されます。(詳細については、前のテキストを参照してください。)

于 2012-05-20T10:53:48.037 に答える
2

SOでこの回答を参照してください。String Interning に関するこのウィキペディアの記事も参照してください。

于 2012-05-20T09:58:30.960 に答える
-1

String s1 = "abc";新しい文字列を作成し、それをインターンします。

String s2 = "abc";s1インターンプールから同じオブジェクトをドラッグします。JVM はパフォーマンスを向上させるためにこれを行います。新しい文字列を作成するよりも高速です。

新しい暗黙的な文字列オブジェクトを返すため、呼び出しnew String()は冗長です。インターンプールから取得しないでください。

Keyser が言うように、==オブジェクトの等価性について文字列を比較し、それらが同じオブジェクトである場合は true を返します。文字列コンテンツを比較するときは、使用する必要があります.equals()

于 2012-05-20T09:52:59.030 に答える