LoginSignup
3
1

More than 5 years have passed since last update.

Integer.valueOf と Auto boxing の罠

Last updated at Posted at 2018-03-02

思わず頭にきたのでメモ書き。

あるメソッドがあります。このメソッドは int を受け取っていました。
ある時、このメソッドが Integer を受け取るように改修が入りました。他はどこも Integer を使っていたからです。
引数の型を書き換えたところ、そのメソッドはコンパイルエラーの一つも出さずに受け入れました。

もうわかるな。NullPointerExceptionだ。

なにがあったの

Integer.valueOf(int)が使われていた。
引数はInteger.valueOf(int)へ流し込まれるにあたり、まず Auto Boxing による変換が挟まり、つまり Integer.valueOf(Integer.intValue()) となった。

Integer は primitive ではないので null になりうる。
null に対してメソッド呼び出しをかけようとすれば当然 NPE で落ちる。
そして Integerint は Auto Boxing で暗黙に相互変換されるため、コンパイラはエラーを吐かない。

Javaなんて嫌いだ。

どうすればいいの

Wrapper Class を使うな古事記 Effective Java にもそう書いてある。

そもそも Wrapper Class という連中はひどくクソッタレな仕様をしている。そもそもラップされている primitive たちと特性を合わせる気がさらさらないのだから笑うしかない。
primitive は mutable なのに Wrapper Class は immutable (intIntegerをそれぞれインクリメントして調べてみるといい!) ってどういうことだ。しかもそれらを暗黙に相互変換だって? 冗談じゃない。
(fix: ややこしいがmutableではなかったので訂正。インクリメントの挙動違いはスタック周り、って最近そういう話がよく出るなあ……)

しかし、現実には Wrapper Class でないと Generics 周りでめんどくさい思いをするハメになる。
特に Optional が使えないのは致命的だ。
仕様上どうしようもないのはわかるが、それはそれとして正直……
Wrapper Class どもに Optional を直接実装してくれりゃあ使い物になったろうにと今でも思う (やれるならやったんだろうが) 。
(もちろん Optional なら OptionalInt がある。が、まとめて扱えないのはやはり欠陥だと思う)

だから、もう一度いう。Wrapper Class を使うな
そして、Wrapper Class が出てきてしまったなら、そいつは Optional だと思え

3
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1