1. まず、String は 8 つの基本データ型に属しません。
オブジェクトのデフォルト値は null であるため、String のデフォルト値も null ですが、これは特別なオブジェクトであり、他のオブジェクトにはないいくつかの特性があります。
2. new String() と new String("") はどちらも、新しい空の文字列を宣言します。これは空の文字列であり、null ではありません。
3. 文字列 str="kvill";
String str=new String ("kvill"); の違い:
ここでは、ヒープやスタックについては説明せず、定数プールの単純な概念を紹介するだけです。
定数プールとは、コンパイル時に決定され、コンパイル済みプールに格納されるプールを指します。クラスファイル内の一部のデータ。これには、文字列定数だけでなく、クラス、メソッド、インターフェイスなどの定数も含まれます。
例 1 を見てください。
次のようにコードをコピーします。
文字列 s0="kvill";
文字列 s1="kvill";
文字列 s2="kv" + "ill";
System.out.println( s0==s1 );
System.out.println( s0==s2 );
結果は次のとおりです。
真実
真実
まず、Java は文字列定数のコピーが 1 つだけ存在することを保証することを知っておく必要があります。
この例の s0 と s1 の "kvill" は両方とも文字列定数であり、コンパイル時に決定されるため、s0==s1 は true となり、"kv" と "ill" も文字列定数になります。複数の文字列定数を使用する場合、それ自体が文字列定数である必要があるため、s2 もコンパイル時に文字列定数に解析されるため、s2 は定数プール Quote 内の「kvill」の 1 つでもあります。
したがって、s0==s1==s2 が得られます。
new String() で作成された文字列は定数ではなく、コンパイル時に決定できないため、 new String() で作成された文字列は定数プールには入れられず、独自のアドレス空間を持ちます。
例 2 を見てください。
次のようにコードをコピーします。
文字列 s0="kvill";
文字列 s1=新しい文字列("kvill");
文字列 s2="kv" + 新しい文字列("ill");
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 );
結果は次のとおりです。
間違い
間違い
間違い
例 2 では、s0 は依然として定数プール内の「kvill」のアプリケーションです。s1 はコンパイル時に決定できないため、s2 には newString の後半が含まれるため、実行時に作成される新しいオブジェクト「kvill」への参照になります。 ("ill") は、コンパイル時に決定できないため、新しく作成されたオブジェクト "kvill" の適用でもあります。これを理解すると、なぜこの結果が得られるのかがわかります。
4. String.intern():
もう 1 つ追加させてください。 に存在します。クラス ファイル内の定数プールは、実行時に JVM によってロードされ、拡張できます。 String の intern() メソッドは、定数プールを拡張するメソッドです。String インスタンス str が intern() メソッドを呼び出すと、Java は定数プール内に同じ Unicode を持つ文字列定数があるかどうかを確認し、存在する場合は返します。そうでない場合は、定数プールに str に等しい Unicode 文字列を追加し、その参照を返します。例 3 を見ると明らかです。
次のようにコードをコピーします。
文字列 s0= "クビル";
文字列 s1=新しい文字列("kvill");
文字列 s2=新しい文字列("kvill");
System.out.println( s0==s1 );
System.out.println( "**********" );
s1.インターン();
s2=s2.intern(); //定数プール内の「kvill」の参照をs2に代入します。
System.out.println(s0==s1);
System.out.println( s0==s1.intern() );
System.out.println( s0==s2 );
結果は次のとおりです。
間違い
**********
false //s1.intern()は実行されるが、その戻り値はs1に代入されない
true // s1.intern() が定数プール内の「kvill」への参照を返すことを示します
真実
最後に、もう一つの誤解を解いておきましょう。
ある人は、「String.intern() メソッドを使用して、String クラスをグローバル String テーブルに保存します。同じ値を持つ Unicode 文字列がすでにこのテーブルにある場合、このメソッドはテーブルにすでにある文字列を返します。アドレス、テーブル内に同じ値を持つ文字列がない場合は、自分のアドレスをテーブルに登録します。「グローバル String テーブルを定数プールとして理解すると、彼の最後の文は、「If に文字列が存在しない場合」です。テーブルに同じ値がある場合、自分のアドレスをテーブルに登録するのは間違いです。
例 4 を見てください。
次のようにコードをコピーします。
文字列 s1=新しい文字列("kvill");
文字列 s2=s1.intern();
System.out.println( s1==s1.intern() );
System.out.println( s1+" "+s2 );
System.out.println( s2==s1.intern() );
結果は次のとおりです。
間違い
クヴィル
真実
このクラスでは、「kvill」定数を宣言していないため、最初は定数プールに「kvill」がありませんでしたが、s1.intern() を呼び出したときに、新しい「kvill」定数が定数プールに追加されました。定数プールにない「kvill」がまだ存在していることがわかります。これは、「定数プールに自分のアドレスを登録していない」ことを意味します。
s1==s1.intern() は false で、元の「kvill」がまだ存在していることを示します。
s2 は定数プール内の「kvill」のアドレスになっているため、s2==s1.intern() は true になります。
5.equals() と == について:
String の場合、これは単に 2 つの文字列の Unicode シーケンスが等しいかどうかを比較し、等しい場合は true を返します。== は 2 つの文字列のアドレスが同じかどうか、つまり参照であるかどうかを比較します。同じ文字列に。
6. 文字列は不変について
String インスタンスが生成されると変更されないことがわかっている限り、これについては多くのことが言えます。たとえば、次のようになります。
文字列定数は 4 つあり、まず「kv」と「ill」で「kvill」が生成され、「kvill」と「」が結合されてメモリに保存されます。 String の「不変性」により多くの一時変数が生成されるため、 StringBuffer を使用することをお勧めします。変更可能。