Arrays.asList()が変わっている

int[] data = new int[] { 1, 2, 3 };
List<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(data));

intをIntegerにAutoBoxingしてくれることを期待したが、コンパイルエラー(汗)asList()がListではなく要素数1のListを返してくる。
今更なのだが、Java5から、Arrays.asList()の仕様が変わっているのだな。

// 正解
list.addAll(Arrays.asList(1, 2, 3));

// 間違い
int[] data = new int[]{ 1, 2, 3 };
list.addAll(Arrays.asList(data));

Java5からasList()は可変引数を取るようになったらしい。

いやしかし、これはあまりにひどい。今回改変されたasList()って、どこで使うんだ?普通にプログラミングしていて、asList()に渡す要素の数が決まっていることなんて定数定義を除けばそうそう無いと思うのだが。RubyやGroovyみたいに配列(リスト)を展開して利用できる*1ならこういうインタフェースでもいいけど、Javaってそんなことできたっけ?

…と、ここまで書いて、もうちょっと試してみた。

List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList(new String[]{ "a", "b", "c" }));

これはOK。

…え?

可変引数を取る部分に配列を与えても、ちゃんと展開してくれるらしい。しかし、プリミティブ型の配列はその限りではないようだ。

System.out.println(Arrays.asList(new Integer[] { 1, 2, 3 }).size());
// => 3

System.out.println(Arrays.asList(new int[] { 1, 2, 3 }).size());
// => 1

オブジェクトの配列であればそれを展開して各要素を持ったListにしてくれる。しかし、プリミティブ型の配列だと展開せず配列全体を1要素としてListを作る。なんじゃそりゃー。

で、結局プリミティブ型の配列から簡単にListを作るにはどうしたらいいんだ?こう?

int[] data = new int[] { 1, 2, 3 };
List<Integer> list = new ArrayList<Integer>();
for(int i : data) {
    list.add(i);
}

ええー。なんかなぁ。でもオブジェクトじゃない以上、仕方がないのか。Java1.4時代となんら変わらないな。

Java5はいろいろ便利な拡張が施されたけれども、なんかいろいろ半端で気持ちが悪い。

*1:例えば、Rubyにおいてmethod(a, b)とmethod(*[a, b])は等しい