0

私の質問は、文字列の宣言と割り当てに関するものです。

通常、文字列を宣言する方法は次のとおりです。

String s1 = "Stackoverflow";

そして、s1 の値を変更する必要がある場合は、次のようにします。

s1 = "new value";

今日、私はそれを行う別の方法を見つけ、文字列を宣言すると次のようになります。

String s2 = new String("Stackoverflow");

そして、値を変更すると次のようになります。

s2 = new String("new value");

私の質問は、2つの違いは何ですか、それとも単に優先的なものですか. コードを見ると4行目

s2 = new String ("new value"); 

それを行うと新しいメモリの場所が作成され、s2 がそれを指すと想定しているので、値を変更するために使用されるとは思えませんが、文字列を宣言するときに使用されていることがわかります。

4

6 に答える 6

0
String s1 = "Stackoverflow";

この行は、まだ存在しない場合、String プールに新しいオブジェクトを作成します。つまり、最初に文字列プールで「Stackoverflow」の検索を試み、見つかった場合は s1 がそれ​​を指し始め、見つからない場合は新しいオブジェクトを作成し、s1 がそれ​​を参照します。

String s2 = new String("Stackoverflow");

値が String プールに既に存在するかどうかに関係なく、常に新しい String オブジェクトを作成します。したがって、ヒープ内のオブジェクトの値は「Stackovrflow」になり、s2 はそれを指し始めます。

s2 = new String("new value");

これにより、再び新しいオブジェクトが作成され、s2 はそれを指し始めます。s2 が指していた以前のオブジェクトは、ガベージ コレクション (gc) 用に開かれていません。

これが役立つかどうか教えてください。

于 2013-10-11T16:23:11.680 に答える
0

主な違いは、コンストラクターが元の String と同じ文字を含む String のまったく新しいインスタンスを常に作成することです。

String s1 = "Stackoverflow";
String s2 = "Stackoverflow";

その後、s1 == s2trueを返します

String s1 = "Stackoverflow";
String s2 = new String("Stackoverflow");

その後、s1 == s2falseを返します

多くの場合、二重引用符オプションを使用する方が適切です。

  • コンストラクターを使用すると、String の 2 つのインスタンスを作成できます。
  • 読みやすく、混乱が少ない
于 2013-10-11T16:17:56.403 に答える
0
String s1 = "Stackoverflow"; // declaring & initializing s1

String s2 = new String("Stackoverflow"); // declaring & initializing s2

上記の場合、String オブジェクトを宣言および初期化しています。

の違い

//first case

String s2 = new String("new String"); // declaring & initializing s2 with new memory

// second case

s2 = "new String" // overwriting previous value of s2

最初のケースでは、新しいオブジェクトを作成しています。s2 によって参照される新しいオブジェクトにメモリを割り当てます。s2 が指していた/参照していた以前のアドレスは、メモリをまだ解放していません。これは、プログラムの終了時またはシステムが必要なときに gc になります。

適切なプログラミング手法(2 番目のケース)は、オブジェクトを一度初期化することです。その値を変更する場合は、null を割り当ててから新しいメモリを割り当てるか、文字列の場合は次のようにします。

s2= "new String";
于 2013-10-11T16:12:09.787 に答える
0

ここに画像の説明を入力

@ user2612619 ここで言いたいのは..「new」演算子でオブジェクトを作成するときはいつでも、それは常にヒープメモリに落ちます。したがって、コンテンツは同じでもオブジェクトが異なる場合は、これによってヒープ上に新しいオブジェクトが作成され、メモリを節約できません....

しかし、メモリを節約するために、Javaの人々はメモリを節約できる場所に不変の概念をもたらしました..同じ内容の別のオブジェクトを作成すると..文字列はdatの違いを認識し、同じ内容のオブジェクトを1つだけ作成し、2つの参照のみを指します1つのオブジェクト..

私はこの図からあなたの疑問を解決することができます..

ケース 1:

String s = new String("stackoverflow");
String s1 = new String("stackoverflow");

それらは2つの異なるハッシュコード値を持つヒープメモリ上の2つの異なるオブジェクトであるため..したがって、s == s1(参照比較です)はfalseです..しかし、s.equals(s1)はコンテンツ比較です..したがってtrueです

ケース 2:

String s = "stackoverflow";
String s1 = "stackoverflow";

ここでオブジェクトはscp(文字列定数プールメモリ)に落ちます2つの異なる参照に対して同じオブジェクト..ハッシュコードも同じ..同じ参照値..ここでs == s1は真です[図から明確に観察できます] s.equals( s1) 内容の比較として正しい..これは非常に美しいコンセプトです..あなたはそれを気に入るでしょう.いくつかの問題を解決する...すべてが最高です.

于 2013-10-11T17:18:36.240 に答える
0

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あり、 はヒープ メモリ内に作成されたオブジェクトを参照しています。s1s3

文字列を作成するための 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によって提供される利点を利用するために文字列を作成する必要がなくなりました。

参考:

  1. 文字列リテラル プール
  2. 部分文字列を使用するためのメモリリークを防ぐために new を使用する
于 2013-10-11T18:21:40.663 に答える