8

重複の可能性:
newを使用した文字列オブジェクトの作成とinternメソッドとの比較

私は文字列をもっと理解するために遊んでいましたが、説明できないことに気づきました:

String str1 = "whatever";
String str2 = str1;
String str3 = "whatever";
System.out.println(str1==str2); //prints true...that's normal, they point to the same object
System.out.println(str1==str3); //gives true..how's that possible ?

最後の行はどのように真になりますか?これは、str1とstr3の両方がメモリ内で同じアドレスを持っていることを意味します。

これは、両方の文字列リテラルが同じ(「何でも」)であり、したがってstr1とstr3が同じオブジェクトに割り当てられていることを検出するのに十分賢いコンパイラ最適化ですか?それとも、文字列の基礎となるメカニズムに何かが欠けていますか?

4

4 に答える 4

8

Javaには一意のインターンインスタンスのプールがあり、その文字列リテラルはこのプールに格納されているためです。これは、最初の「whatever」文字列リテラルが3番目の「whatever」リテラルとまったく同じStringオブジェクトであることを意味します。

ドキュメントが言うように:

public String intern()

文字列オブジェクトの正規表現を返します。最初は空の文字列のプールは、Stringクラスによってプライベートに維持されます。

インターンメソッドが呼び出されたときに、equals(Object)メソッドによって決定されたこのStringオブジェクトに等しい文字列がプールにすでに含まれている場合、プールからの文字列が返されます。それ以外の場合、このStringオブジェクトはプールに追加され、このStringオブジェクトへの参照が返されます。

したがって、任意の2つの文字列sおよびtについて、s.equals(t)が真である場合に限り、s.intern()== t.intern()が真になります。

すべてのリテラル文字列と文字列値の定数式がインターンされます。文字列リテラルは、Java言語仕様の§3.10.5で定義されています

戻り値:この文字列と同じ内容の文字列ですが、一意の文字列のプールからのものであることが保証されています。


于 2012-11-19T08:59:32.037 に答える
6

http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3

投稿が言うように:

文字列の割り当ては、すべてのオブジェクトの割り当てと同様に、時間とメモリの両方でコストがかかることがわかります。JVMは、文字列リテラルをインスタンス化するときにいくつかのトリックを実行して、パフォーマンスを向上させ、メモリのオーバーヘッドを削減します。JVMで作成されるStringオブジェクトの数を減らすために、Stringクラスは文字列のプールを保持します。コードが文字列リテラルを作成するたびに、JVMは最初に文字列リテラルプールをチェックします。文字列がすでにプールに存在する場合、プールされたインスタンスへの参照が返されます。文字列がプールに存在しない場合、新しいStringオブジェクトがインスタンス化され、プールに配置されます。

于 2012-11-19T09:00:13.463 に答える
2

もし、するなら:

String str1 = new String("BlaBla");  //In the heap!
String str2 = new String("BlaBla");  //In the heap!

次に、演算子(およびコンストラクター)を使用してStringオブジェクトを明示的に作成します。newこの場合、各オブジェクトが異なる保存場所を指していることになります。

しかし、あなたがそうするなら:

String str1 = "BlaBla";        
String str2 = "BlaBla";

次に、暗黙の構築を行います。2つの文字列リテラルが同じ値を持つ場合、同じストレージを共有します。これは、Javaが同じ文字列のストレージを保存するためです。(同じ値の文字列)

于 2012-11-19T09:03:40.093 に答える
1

コンパイラはjavac、特定のクラスファイルで同じ文字列リテラルを結合します。

ただし、実行時に、文字列リテラルはString.intern()と同じアプローチを使用して結合されます。これは、異なるアプリケーション(同じオブジェクトを使用する同じJVM内)の異なるクラスの文字列であっても意味します。

于 2012-11-19T09:03:08.703 に答える