通常、次のようなnew
キーワードを使用してオブジェクトを作成します。
Object obj = new Object();
文字列はオブジェクトですが、new
を使用して作成しません。
String str = "Hello World";
どうしてこれなの? new
を使用して文字列を作成できますか?
すでに述べたことに加えて、String literals [つまり、"abcd"
のような文字列で、new String("abcd")
]のようなものではないJava 「abcd」を参照するときは、毎回新しいインスタンスではなく、単一のString
インスタンスへの参照を取得します。
String a = "abcd";
String b = "abcd";
a == b; //True
しかし、あなたが持っていた場合
String a = new String("abcd");
String b = new String("abcd");
それから持つことが可能です
a == b; // False
(そして、誰もが思い出させる必要がある場合、常に.equals()
を使用して文字列を比較します; ==
物理的同等性のテスト)。
ストリングリテラルのインターンは、複数回使用されることが多いため良いです。たとえば、(工夫された)コードを考えてみましょう:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
文字列のインターンがなかった場合、「次の反復」は10回インスタンス化する必要がありますが、現在は1回のみインスタンス化されます。
文字列は、Javaの「特別な」オブジェクトです。 Javaデザイナーは、文字列は頻繁に使用されるため、独自の構文とキャッシュ戦略が必要であると判断しました。
String myString = "something";
myStringは、値が「something」のStringオブジェクトへの参照です。後で宣言する場合:
String myOtherString = "something";
Javaは、myStringとmyOtherStringが同じであり、それらを同じオブジェクトとしてグローバルなStringテーブルに格納することができるほど賢いです。これを行うために文字列を変更できないという事実に依存しています。これにより、必要なメモリ量が減り、比較を高速化できます。
代わりに、あなたが書く場合
String myOtherString = new String("something");
Javaは、myStringオブジェクトとは異なるまったく新しいオブジェクトを作成します。
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
これでいくつかの疑問が解消されることを願っています。 :)
ショートカットです。元々はそうではありませんでしたが、Javaで変更しました。
この [〜#〜] faq [〜#〜] は、それについて簡単に説明しています。 Java仕様ガイドもそれについて述べています。しかし、私はそれをオンラインで見つけることができません。
文字列は(より良いフレーズを求めて)最適化の対象となります。 Stringには、他のオブジェクトとは異なり、演算子のオーバーロード(+演算子の場合)もあることに注意してください。したがって、これは非常に特殊なケースです。
Javaでは、文字列は特殊なケースであり、文字列にのみ適用される多くのルールがあります。二重引用符により、コンパイラはStringオブジェクトを作成します。 Stringオブジェクトは不変であるため、コンパイラーは複数のストリングをインターンし、より大きなストリングプールを構築できます。 2つの同一の文字列定数は、常に同じオブジェクト参照を持ちます。これが当てはまらない場合は、新しいString( "")を使用できます。これにより、実行時にStringオブジェクトが作成されます。動的に作成された文字列を文字列検索テーブルに対してチェックするために、以前はintern()メソッドが一般的でした。文字列がインターンされると、オブジェクト参照は正規のStringインスタンスを指します。
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
クラスローダーがクラスをロードすると、すべての文字列定数が文字列プールに追加されます。
リテラルプールには、キーワードnew
を使用せずに作成された文字列が含まれます。
違いがあります:新しい参照のない文字列は文字列リテラルプールに格納され、新しい文字列はヒープメモリにあると言います。
Newを含む文字列は、他のオブジェクトと同様にメモリ内の他の場所にあります。
で新しい文字列を作成してください
String s = new String("I'm a new String");
通常の表記法s = "new String";
は多かれ少なかれ便利なショートカットです。パフォーマンスの理由で使用する必要があります。ただし、really方程式に適格な文字列が必要な非常にまれなケースを除きます。
(string1.equals(string2)) && !(string1 == string2)
[〜#〜] edit [〜#〜]
コメントへの応答:これは、ではなく助言を意図したものであり、質問者の論文に対する単なる直接的な応答であり、 Stringsに 'new'キーワードを使用しないでください。これは単に正しくありません。この編集(上記を含む)がこれを少し明確にすることを願っています。ところで-上記のSOに関する質問には、いくつかの優れた、はるかに優れた答えがあります。
構文糖。の
String s = new String("ABC");
構文はまだ利用可能です。
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
出力:
本当だ
2つの個別のオブジェクトを作成しましたが、どちらにもfield(ref) 'Name'があります。したがって、この場合でも、Java Deals ..
new String("string")
は引き続き使用できますが、文字列リテラルなしで新しい文字列を作成することは難しくなります...文字配列またはバイトを使用する必要があります:-)文字列リテラルには1つの追加プロパティがあります:すべて同じ文字列リテラル任意のクラスポイントから同じ文字列インスタンスまで(インターンされます)。
StringはJavaの不変クラスであるためです。
なぜ不変なのでしょうか? Stringは不変なので、複数のスレッド間で共有でき、外部でString操作を同期する必要はありません。 As Stringはクラスローディングメカニズムでも使用されます。したがって、Stringが可変の場合、Java.io.writerはabc.xyz.mywriterに変更された可能性があります
リテラル(引用符内の文字)はすでにHostクラスのロード時に作成されたStringオブジェクトであるため、文字列を新たに作成する必要はほとんどありません。リテラルとドンでメソッドを呼び出すことは完全に合法です。主な違いは、リテラルによって提供される利便性です。 charの配列を作成し、charごとにそれを埋め、それらが新しいString(char array)を実行する必要がある場合、それは大きな苦痛と無駄です。