Personal tools
You are here: Home ブログ nakayama Tiger! Tiger!
Document Actions

Tiger! Tiger!

福島さんに、

> J2SE5.0では、javacがうまくStringを、StringBuilderに変換してくれるそうです。
> http://www.javainthebox.net/laboratory/J2SE1.5/TinyTips/StringBuilder/StringBuilder.html

ということを教えてもらいました。
Javaで文字列を連結するときはStringBufferを使うというのが鉄則でしたが、常識は変わるものです。
もっとも、うまい話を素直に信じないのが技術屋です。
というわけで、調査してみました。

最初に用意したのは、こんなコード。

class Hoge {
    public static void main(String[] arg) {
        String s = "hoge";
        s += "huga" + "muga";
        s += "huuu";
        System.out.println(s);
    }
}

JDKのjavacでコンパイルして、javapで逆アセンブルすると、

Compiled from "Hoge.java"
class Hoge extends java.lang.Object{
Hoge();
  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 hoge
   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 hugamuga
   16: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
   19: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
   22: astore_1
   23: new #3; //class java/lang/StringBuilder
   26: dup
   27: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
   30: aload_1
   31: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
   34: ldc #8; //String huuu
   36: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
   39: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
   42: astore_1
   43: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
   46: aload_1
   47: invokevirtual #10; //Method java/io/PrintStream.println:
(Ljava/lang/String;)V
   50: return
}

と出ました。読みにくいので、適当にハンド逆コンパイルすると、

class Hoge {
    public static void main(String[] arg) {
        StringBuilder sb1 = new StringBuilder();
        sb.append("hoge");
        sb.append("hugamuga");
        String s1 = sb1.toString();
        StringBuilder sb2 = new StringBuilder();
        sb.append(s1);
        sb.append("huuu");
        String s2 = sb2.toString();
        System.out.println(s2);
    }
}

となります。
StringBuilderを二つも作ってたりして、ちょっと頭の悪いコードです。
うまくやっている感じはしません。

次に用意したのはこんなの。

class Hoge {
    public static void main(String[] arg) {
        String s = "00000";
        s += "aaaa";
        s += "bbbb";
        s += "cccc";
        s += "dddd";
        s += "eeee";
        s += "ffffff";
        System.out.println(s);
    }
}

コンパイルして、逆アセンブルすると、StringBuilderとStringを6個ずつ生成しています。
お話になりません。

でも、

class Hoge {
    public static void main(String[] arg) {
        String s = "00000";
        s += s + s + s + s + s + s + s;
        System.out.println(s);
    }
}

では、StringBuilderとStringは1個ずつしか生成されず、一つのStringBuilderに対してappend()が繰り返し呼ばれています。
どうも、Javaの一行に対してStringBuilderが一つ生成されるようです。

結論
・Javaのソースコード上、一行で連結を完結できる場合は+演算子で連結する (条件はこれであってる?)
・それ以外はStringBuilderで連結する

使い分けが面倒なら、常にStringBuilderを使います。
ただし、

・スレッド間で共有されるインスタンス変数やクラス変数は、従来通りStringBufferを使う

という条件は、常につきまといます。

Category(s)
覚え書き
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/anaka/tiger-tiger/tbping

Re:Tiger! Tiger!

Posted by fukushima at 2006-02-22 10:47
ここまで調べるという姿勢がさすが中山さんですね。
脱帽です。
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.