重複の可能性:
Javaの文字列プールに関する質問
javaStringsオブジェクトの作成に疑問があります。
String s1 = "Hello"+"world";
String s2 = s1+"Java";
このプログラムでは、作成されるStringオブジェクトの数とその方法を説明してください。ありがとう。
重複の可能性:
Javaの文字列プールに関する質問
javaStringsオブジェクトの作成に疑問があります。
String s1 = "Hello"+"world";
String s2 = s1+"Java";
このプログラムでは、作成されるStringオブジェクトの数とその方法を説明してください。ありがとう。
答えは3です
JVMの開始ごとに2つのStringオブジェクトが1回作成されます。
どちらも定数(コンパイル時に認識される)であるため、インターンされます。
これらは、このコードが実行されるたびに再利用されます。上記の2つの文字列を連結するためにStringBuilderが作成されます。それらへの参照はs1とs2に割り当てられます。
コードのバイトコードは次のとおりです。
0: ldc #37; //String Helloworld
2: astore_1
3: new #39; //class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #41; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #47; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #50; //String Java
16: invokevirtual #52; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #56; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
23: return
String
JVM の実装が異なるため、いくつかの違いがあるため、作成される の数を正確に言うことはできません。
不変クラスであるため、 String
素朴な答えは5です。StringBuffer
StringBuilder
String
連結は -calls を介して要約されappend()
ます。
編集:ここでいくつかの異なる答えがあるので、私が5と言った理由を説明します:
コンパイルされたコードを見ると、次のことが簡単に推測できます。
String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();
実行前にコンパイラによって多くの最適化が行われるため、ソース コードを見ただけでは正確に知ることはできません。
ここでは、s1 用に 1 つの String オブジェクトが作成され、s2 用に別の String オブジェクトが作成されていることがわかります。ここでは、文字列プールに「Helloworld」と「Java」の 2 つの文字列リテラルがあります。
Program.class を逆コンパイルすると、実際のコードが表示されます
String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();
10個のオブジェクトのようです。各文字列内にはchar[] value
、これが別のオブジェクト+ StringBuilder内の別のchar []であるためです
答えは 3 です。
逆アセンブルされた結果は、次の方法で表示できます。
javap -verbose YourClass
定数プールには次が含まれます。
...
const #17 = Asciz Helloworld;
...
const #30 = Asciz Java;
...
これは、2 つの文字列 ("Helloworld" と "Java") が、定数プールに自動的にインターンされるコンパイル時の定数式であることを意味します。
コード:
Code:
Stack=3, Locals=3, Args_size=1
0: ldc #16; //String Helloworld
2: astore_1
3: new #18; //class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #29; //String Java
16: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
23: return
これは、s2 が StringBuilder.append() および toString() によって作成されたことを示します。
これをさらに興味深いものにするために、javac は定数折りたたみでコードを最適化できます。次のコードで作成された文字列の数を推測できます。
final String s1 = "Hello" + "world";
String s2 = s1 + "Java";
「最終」は、s1 が定数であることを意味し、javac が s2 およびインターン s2 の値を構築するのに役立ちます。したがって、ここで作成される文字列の数は 2 です。
はい、5 つの String オブジェクトが作成されます。文字列は不変です。手順は次のとおりです。1. 最初に「Hello」 2. 次に別のオブジェクト「Hello World」 3. 次に別のオブジェクト「Java」 4. 次に s1+「Java」、最後に s2 が作成されます。
実際には、2 つの String リテラルだけで String オブジェクトは作成されません。あなたが持っているように文字列が初期化されるとき、それらはオブジェクトではなくリテラルです。String オブジェクトを作成する場合は、次のようにします。
String a = new String("abcd");