2

重複の可能性:
Javaの文字列プールに関する質問

String s1 = "length";
String s2 = "length";
System.out.println("EQUAL: " + (s1 == s2));
String s3 = "length: 10";
String s4 = "length: " + s3.length();
System.out.println(s3.length());
System.out.println(s4.length());
System.out.println("EQUAL: " + (s3 == s4));

出力:

EQUAL:true//文字列プール内の同じ文字列参照を理解しました

10

10

EQUAL:false //なぜですか?

4

3 に答える 3

4
 String s4 = "length: " + s3.length();

新しいStringオブジェクトを作成します。

したがって、s3は別のオブジェクトを参照し、s4は別のオブジェクトを参照します。これにより、==条件が返されfalseます。

于 2012-10-02T14:47:15.227 に答える
1

'new'演算子はありません。それで、すべてが定数プールで作成されている必要がありますが、重複する値を持つことはできませんか?

String s4 = "length: " + s3.length();

とほとんど同じです

String s4 = new StringBuilder().append("length: ")
                               .append(Integer.toString(s3.length()))
                               .toString();

したがって、かなりの数の新しいオブジェクトと新しい文字列が作成されます。

于 2012-10-02T14:57:12.133 に答える
1

オブジェクト(および配列)の「==」は物理的な同等性です。つまり、オブジェクトaとbの場合、aとbが同じオブジェクトを指している場合、a==bは真です。

コンパイラはあなたのためにいくつかの最適化を行います。たとえば、文字列「length」は定数として1回だけ保存されます。したがって、s1とs2は同じ(定数)文字列を指します。

おそらく、出力されたバイトコードを確認するのに役立ちます。これは、非標準のJavaコンパイラから生成されたjasminアセンブリコードであることに注意してください。「javap-c」を実行することで、Javaコンパイラが同様のことを行うことを確認できます(ただし、出力は読みにくくなります)。


定数文字列「長さ​​」への参照をロードし、s1に格納します。

ldc "length"
astore_1

(同じ)定数文字列 "length"への参照をロードし、s2に格納します。

ldc "length"
astore_2

結果を比較して印刷します。読みすぎではありません。

getstatic java/lang/System/out Ljava/io/PrintStream;
new java/lang/StringBuffer
dup
invokespecial java/lang/StringBuffer/<init>()V
ldc "EQUAL: "
invokevirtual java/lang/StringBuffer/append(Ljava/lang/String;)Ljava/lang/StringBuffer;
aload_1
aload_2
if_acmpeq true0
iconst_0
goto end1
true0:
iconst_1
end1:
invokevirtual java/lang/StringBuffer/append(Z)Ljava/lang/StringBuffer;
invokevirtual java/lang/StringBuffer/toString()Ljava/lang/String;
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V

「長さ:10」をロードし、s3に保存します

ldc "length: 10"
astore_3

「length:」を長さと連結し、s4に格納します。連結すると、新しい文字列(したがって新しい参照)が作成されることに注意してください。

new java/lang/StringBuffer
dup
invokespecial java/lang/StringBuffer/<init>()V
ldc "length: "
invokevirtual java/lang/StringBuffer/append(Ljava/lang/String;)Ljava/lang/StringBuffer;
aload_3
invokevirtual java/lang/String/length()I
invokevirtual java/lang/StringBuffer/append(I)Ljava/lang/StringBuffer;
invokevirtual java/lang/StringBuffer/toString()Ljava/lang/String;
astore 4

前と同じように印刷して戻ります。


ご覧のとおり、最初の2つの変数は、「定数プール」内の同じ文字列を参照しています。変数s3も定数プール内の文字列を参照していますが、s4は定数文字列と数値から作成された新しい文字列を参照しています。

ところで、この動作に依存するべきではありません。

于 2012-10-02T15:14:56.050 に答える