クラスファイルで見る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")が使えます。