AutoUnboxingの落とし穴
久しぶりにJavaをデバッグしてて思わぬところで悩んだのでメモ。久しぶりのJavaネタです。
String s = convHoge(p.id);
スタックトレースを確認するとこの行でNullPointerExceptionが発生していました。メソッド内のトレースは含まれていないので間違いなくこの行が問題の部分です。
しかし、デバッグで変数 p を確認してみるとnullではなくインスタンスは存在している。そんな筈はないと暫くの間Inspectorとにらめっこしていたわけですが、問題点は思わぬ別のところにありました。
public class P { Integer id; }
public String convHoge(int i) { return String.valueOf(i); }
メソッドの第一引数の型がコールする側がInteger型、受ける側がint型となっていました。メソッドをコールするタイミングで代入時の暗黙の型変換が行われていて、そこでNullPointerExceptionが発生していたことになります。結論からするとp.idがnullだったわけです。
int i = p.id.intValue();
暗黙的にこのような挙動をしています。
ここで紹介しているソースはかなり簡略化していますがかなり悩みました。
Java1.4ではそもそもコンパイルエラーなのですが、S2SE5.0からautoboxing/unboxingという機構が加わり、数値ラッパ型とプリミティブ型が代入により許容される仕様となりました。
オブジェクト型とプリミティブ型はメモリ管理的にも異なっていることもあり、型変換を明示しないautoboxingの仕様は個人的には否定的です。暫くJavaから離れていた身なのでメリットもよくわからず、ただただ気持ち悪いのですが実際のところはどうなんでしょうかね?