文字列 a と b を想定:
a += b
a = a.concat(b)
内部的には、それらは同じものなのでしょうか?
参考までに、concat を逆コンパイルしたものがこちらです。演算子も逆コンパイルして、それが何を行うのかを確認したいと思います+
。
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
ベストアンサー1
いいえ、そうではありません。
まず、セマンティクスに若干の違いがあります。a
がの場合null
、a.concat(b)
は をスローしますNullPointerException
が、の元の値はであるかのようにa+=b
扱われます。さらに、メソッドは値のみを受け入れますが、演算子は引数を暗黙的に文字列に変換します (オブジェクトの メソッドを使用)。そのため、メソッドは受け入れるものに関してより厳密です。a
null
concat()
String
+
toString()
concat()
中身を見るには、簡単なクラスを書いてa += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
次に、javap -c
(Sun JDK に含まれています) を使用して逆アセンブルします。次の内容を含むリストが表示されます。
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
a += b
つまり、
a = new StringBuilder()
.append(a)
.append(b)
.toString();
このconcat
メソッドはより高速になるはずです。ただし、文字列の数が多い場合はStringBuilder
、少なくともパフォーマンスの点では、このメソッドの方が優れています。
String
およびのソース コードStringBuilder
(およびそのパッケージ プライベート基本クラス) は、Sun JDK の src.zip で入手できます。char 配列を構築し (必要に応じてサイズを変更)、最終的な を作成するときにそれを破棄していることがわかりますString
。実際には、メモリ割り当ては驚くほど高速です。
更新: Pawel Adamski が指摘しているように、最近の HotSpot ではパフォーマンスが変化しています。 はjavac
依然としてまったく同じコードを生成しますが、バイトコード コンパイラが不正行為をします。コード全体が破棄されるため、単純なテストは完全に失敗します。System.identityHashCode
( ではなくString.hashCode
) を合計すると、コードがわずかに有利であることがわかりますStringBuffer
。次の更新がリリースされたとき、または別の JVM を使用したときに変更される可能性があります。翻訳:、HotSpot JVM 組み込み関数のリスト。