char から String への型変換

2009-11-03 追記:
グーグルから飛んでこられる方が多いので、結論を追記。

char --> String への変換方法

char c = 'a';
String.valueOf(c);

char[] --> String への変換方法

char[] cs = new char[10];
cs[0] = 'a';
cs[1] = 'b';
String.valueOf(cs);

以下、当時の検証内容。結論だけ知りたい方は読む必要なしです。

    • -

何気に本日書いた

char[] c = new c[1];
c[0] = ...;
...
String s = new String(c);
....

というような処理。

が、帰宅途中に気になってきたのが上記の部分。要するに char 配列を引数に String を生成したのだ。これ、

String.valueOf(c[0]);

と書くこともできる。どっちがいいの?まさか、String.valueOf を使うとすごい最適化してくれたりしないよね(もう new String で書いちゃったし!)というのが気になった。


valueOf() の方は、

    public static String valueOf(char c) {
	char data[] = {c};
	return new String(0, 1, data);
    }

// new String() は・・・

    // Package private constructor which shares value array for speed.
    String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
    }

要するに、valueOf(char c) は参照渡しではなくて、値渡しなんで、そのままそれを内部配列として使用して String インスタンスにしているのね。


一方、new String(c); の方は・・・・

    public String(char value[]) {
	int size = value.length;
	this.offset = 0;
	this.count = size;
	this.value = Arrays.copyOf(value, size);
    }

なるほど。こっちは char 配列で、参照渡しなので、配列のコピーを行う。Arrays.copyOf() の実装は、、、

    public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

となっている。最終的には System.arraycopy() でコピーしているわけだ。


ということで、残念ながら私の実装は外れの方だったようだ。明らかに valueOf() の方がいいだろう。別に大きな差が出るとは思わないが、ループの中で 100 万回呼ばれる可能性もある処理だし、わかってて外れを書くのも気分がよくない。直すことにしよう・・・。


教訓としては、こういう生成系の処理において、イミュータブルなオブジェクトかプリミティブ型の引数が存在する場合は、そっちを使うようにしたほうがいいということ。逆に言えば、生成系処理を書く場合、その引数がイミュータブルかどうかは意識して処理を変えた方がいいということ。・・・お、今俺あたりまえのこといいましたヨー。


追記:
なんかもうこの処理全体的に気に入らなくなってきた。全部書き直すことに決めた。