StringとStringBuilderの違い
StringとStringBuilderの最も主要な違いは文字列接続操作の効率に現れている.
Stringは、リロード演算子+または+=を使用して文字列接続を行い、次のコードがあります.
Javapによる逆コンパイルにより、JVMによって生成されたバイトコードを得ることができます.
mainメソッドでは、JVMはnewのStringBuilderオブジェクトであり、appendメソッドを呼び出して文字列接続操作を行うことがわかります.
それなら、StringBuilderオブジェクトを使用するのではなく、Stringを直接使用して、JVMに自動的に最適化させることができますか?
次のコードを参照してください.
同様に逆コンパイルを行います.
注意:
implicitメソッドはStringの+操作を使用して文字列接続を行い、バイトコードの8-35行目を観察します.これはループです.new StringBuilderオブジェクトの操作はループ内で行われていることがわかります.これは、ループのたびに新しいStringBuilderオブジェクトが作成されることを示しています.
explicitメソッドはStringBuilderオブジェクトを使用するappendメソッドを文字列接続し、JVMは0行目にStringBuilderオブジェクトを作成し、ループは13~27行目で、StringBuilderを使用して文字列接続を行うとStringBuilderオブジェクトが1つしか作成されません.
以上よりStringBuilderの文字列接続の操作効率はStringよりはるかに高いことが分かった.
StringBuilderのスレッドセキュリティ特性は、追加のオーバーヘッドをもたらすため、StringBufferの効率はStringBufferよりもやや高い.
Stringは、リロード演算子+または+=を使用して文字列接続を行い、次のコードがあります.
public class Concatenation {
public static void main(String[] args) {
String str = "My";
String introduction = str + " name " + " is " + " cgw ";
System.out.println(introduction);
}
}
Javapによる逆コンパイルにより、JVMによって生成されたバイトコードを得ることができます.
public Concatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String My
2: astore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6; //String name
16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: ldc #7; //String is
21: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: ldc #8; //String cgw
26: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
29: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
32: astore_2
33: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
36: aload_2
37: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: return
}
mainメソッドでは、JVMはnewのStringBuilderオブジェクトであり、appendメソッドを呼び出して文字列接続操作を行うことがわかります.
それなら、StringBuilderオブジェクトを使用するのではなく、Stringを直接使用して、JVMに自動的に最適化させることができますか?
次のコードを参照してください.
import java.lang.StringBuilder;
public class WhitherStringBuilder {
public String implicit(String[] fields) {
String result = "";
for(int i = 0 ; i < fields.length ; i++) {
result += fields[i];
}
return result;
}
public String explicit(String[] fields) {
StringBuilder result = new StringBuilder();
for(int i = 0 ; i < fields.length ; i++) {
result.append(fields[i]);
}
return result.toString();
}
}
同様に逆コンパイルを行います.
public class WhitherStringBuilder extends java.lang.Object{
public WhitherStringBuilder();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public java.lang.String implicit(java.lang.String[]);
Code:
0: ldc #2; //String
2: astore_2
3: iconst_0
4: istore_3
5: iload_3
6: aload_1
7: arraylength
8: if_icmpge 38
11: new #3; //class java/lang/StringBuilder
14: dup
15: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
18: aload_2
19: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_1
23: iload_3
24: aaload
25: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_2
32: iinc 3, 1
35: goto 5
38: aload_2
39: areturn
public java.lang.String explicit(java.lang.String[]);
Code:
0: new #3; //class java/lang/StringBuilder
3: dup
4: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
7: astore_2
8: iconst_0
9: istore_3
10: iload_3
11: aload_1
12: arraylength
13: if_icmpge 30
16: aload_2
17: aload_1
18: iload_3
19: aaload
20: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: iinc 3, 1
27: goto 10
30: aload_2
31: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
34: areturn
}
注意:
implicitメソッドはStringの+操作を使用して文字列接続を行い、バイトコードの8-35行目を観察します.これはループです.new StringBuilderオブジェクトの操作はループ内で行われていることがわかります.これは、ループのたびに新しいStringBuilderオブジェクトが作成されることを示しています.
explicitメソッドはStringBuilderオブジェクトを使用するappendメソッドを文字列接続し、JVMは0行目にStringBuilderオブジェクトを作成し、ループは13~27行目で、StringBuilderを使用して文字列接続を行うとStringBuilderオブジェクトが1つしか作成されません.
以上よりStringBuilderの文字列接続の操作効率はStringよりはるかに高いことが分かった.
StringBuilderのスレッドセキュリティ特性は、追加のオーバーヘッドをもたらすため、StringBufferの効率はStringBufferよりもやや高い.