オートボクシングの勘違いというか認識不足というか

5.0から、Auto-boxing/Auto-unboxingの機能が追加になった。
これって、Collection関連のときのみ有効だとずーっと思ってた。
つまり、こんな感じ。


List list = new ArrayList();
for (int i = 0; i < 100; i++) {
list.add(i);
}


でも実は、Collectionとか関係なく、どこでも使えちゃうものだった。
例えば、こんな風に。


Integer sum = 0;
for (Integer i = 1; i <= 1000000; i++) {
sum += i;
}
return sum;


intで十分なのに、Integerをつかっちゃったコード。
こんなふうに間違って使うと、めっちゃパフォーマンスが悪くなる(はず)。


試しに、こんなクラスを実行してみる。


public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
long start1 = System.currentTimeMillis();
exec1();
long end1 = System.currentTimeMillis();

long start2 = System.currentTimeMillis();
exec2();
long end2 = System.currentTimeMillis();

System.out.println("exec1: " + (end1 - start1));
System.out.println("exec2: " + (end2 - start2));
}
}

private static int exec1() {
Integer sum = 0;
for (Integer i = 1; i <= 1000000; i++) {
sum += i;
}
return sum;
}

private static int exec2() {
int sum = 0;
for (int i = 1; i <= 1000000; i++) {
sum += i;
}
return sum;
}

まちがっちゃったexec1と、まちがってないexec2を10回ほど実行して、
それぞれ時間を出力する。
# とりあえずどーでもいい測定なので、細かいことは気にしない。


実行結果。


exec1: 47
exec2: 0
exec1: 31
exec2: 15
exec1: 32
exec2: 0
exec1: 31
exec2: 0
exec1: 31
exec2: 0
exec1: 47
exec2: 0
exec1: 31
exec2: 0
exec1: 32
exec2: 0
exec1: 31
exec2: 0
exec1: 31
exec2: 0
だんぜん、exec1が遅いっすね。


興味本位で逆コンパイルした結果。


private static int exec1()
{
Integer sum = Integer.valueOf(0);
for(Integer i = Integer.valueOf(1); i.intValue() <= 0xf4240; i = Integer.valueOf(i.intValue() + 1))
sum = Integer.valueOf(sum.intValue() + i.intValue());

return sum.intValue();
}

ありえないコードっす。。。