Integerの内部動作
で、僕としてはなんでnewではなくてvalueOfにしてあるのか、というのに非常に疑問を持ったわけです。どっちでもいいじゃないかと。それどころか、Integer.valueOf(int i)というのは、java1.5でわざわざ追加されたものなのです(参考:1.4の仕様と1.5の仕様)。そのため、Integerのソースファイルを追いかけてみることにしました。
さて、ここで問題です。以下のプログラムは何を出力するでしょうか。
class Test{ public static void main(String [] argv){ System.out.println(new Integer(1) == new Integer(1)); System.out.println(new Integer(1000) == new Integer(1000)); System.out.println(Integer.valueOf(1) == Integer.valueOf(1)); System.out.println(Integer.valueOf(1000) == Integer.valueOf(1000)); } }
正解は・・・・
false false true false
この理由は、ソースファイルの気持ち悪い内容にありました。
class Integer{ public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); } }
何をやっているかというと、-128から127までの数がやってきた場合は、すでに生成してあるオブジェクトを返してやろうということです。これはboxing処理のためだけに追加されたメソッドであって、boxing処理で使われるのは-128から127までの値がほとんどだろうという予想(もしくは実験)があったのだと思われます。それらについては、newというメモリを食ってさらにガベコレにも影響するものをわざわざ行わず、キャッシュから取ってきた方がいいだろうということなのでしょう。
っていうか、IntegerCacheなんていう気持ち悪いものが裏で動いているとは知らなかった・・・・
そもそも、どこのパッケージにあるのかとか調べてみても見つからない・・・Javaの隠れ仕様ということなのか。