きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

クラスファイルで見るJavaのAutoBoxing

昔書いたことがあるけど気が向いたのでjavapの結果もそえてみよう。

面倒臭いからClass File Editorの結果で勘弁してほしい。

まあいまさら書くことでもないんだけど。

 

    	Integer boxing_i = 1;
	int unboxing_i = boxing_i;

上記のコードがこんな感じになります。

     0  iconst_1
     1  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [16]
     4  astore_1 [boxing_i]
     5  aload_1 [boxing_i]
     6  invokevirtual java.lang.Integer.intValue() : int [22]
     9  istore_2 [unboxing_i]

ポイント

  • ボクシングではvalueOf(int)が使用される
  • アンボクシングではintValue()が使用される

long、short、char、byte、float、doubleも同じ理屈。

 

対応表

primitive wrapper Boxing Unboxing
byte java.lang.Byte Byte.valueOf(byte) byteValue()
char java.lang.Character Character.valueOf(char) charValue()
short java.lang.Short Short.valueOf(short) shortValue()
int java.lang.Integer Integer.valueOf(int) intValue()
long java.lang.Long Long.valueOf(long) longValue()
float java.lang.Float Float.valueOf(float) floatValue()
double java.lang.Double Double.valueOf(double) doubleValue()

 

AutoBoxingと性能

valueOf()はキャッシュを探します。

しかしながら、キャッシュにヒットするとは限らない。

キャッシュの範囲はJRE依存です。特に決まりがない。

Sunは過去にIntegerのキャッシュ範囲を変更するシステム・プロパティを提供し、

そのあとに-XXオプションまで出している。

そのへんの話は過去のエントリーでも見てみてください。

数字のキャッシュ

キャッシュ範囲外であれば当然新しいインスタンスができる。

危険なケースはループ内、Unboxingした後のBoxing

そこまでたいそうな性能問題ではないが、

コードを書いてる時くらいにしか気付けない類の性能問題。

 

AutoBoxingの予防策

コンパイラオプションで警告をだせます。

Window > Preferences > Java > Compiler > Errors/Warnings

Potential programming problemsから

Boxing and unboxing conversionsを"Ignore"から"Warning"に変更。

 

また、このコンパイル警告には@SuppressWarnings("boxing")が使えます。