Java SE 8でOptionalIntを使ってみよう
最近はJava SE 8の研修を開発しています。
Java SE 8の新機能を、要点を絞って1日間で学べる研修にする予定です。
Java SE 8新機能の目玉と言えばラムダ式ですが、地味に便利なのがjava.util.OptionalIntクラスです。
Optionalというクラスについては、きしださんが詳しくブログに書かれています。
Java8でのプログラムの構造を変えるOptional、ただしモナドではない - きしだのはてな
Java8のOptionalがモナドになったよ! - きしだのはてな
また、Java SE 8ローンチイベントでも講演されています。
祝☆Java 8 Launch - null書いたら負け!Java8コーディング作法 @kis #jjug - YouTube
Optionalクラスというのは、中に値を保持するだけのクラスです。
従来、値の「ある・なし」は「nullでないか・nullか」で判断していたことが多かったと思います。
しかし、nullを利用すると、思いもよらないところでNullPointerExceptionが起こってしまったり、バグの温床になります。
Optionalを利用することで、nullを使わずに値の「ある・なし」を判断できるようになり、上記のようなバグを未然に防ぐことができます。
Optionalは、中に保持する値の型はジェネリクスで指定するため、intなどの基本データ型では使えません。
そこで、Java SE 8では、Optionalの基本データ型としてOptionalInt・OptionalDouble・OptionalLongというクラスが用意されています。
それぞれint・double・longを保持するクラスです。
基本データ型なのでNullPointerExceptionの心配は無いのですが、これらを利用すると、値の「ある・なし」を明確に表すことができます。
例えば、配列のインデックスを引数とし、それに該当する要素を返すメソッドを考えます。
Java SE 7までは(もっと言うとC言語の時代は)、こんな風に書かれていたと思います。
getValue()メソッドは、インデックスが配列の範囲外だった場合のフラグとして、-1を返しています。
このコードの弱点は、getValue()メソッドが-1を返した時に、インデックスが配列の範囲外だったのか、指定したインデックスに本当に-1という値があったのかが、判定できないことです。
じゃあ-1じゃなくて別の値(例えば-1000とか)にすりゃあいいじゃんとも思いますが、それでも、その値が配列内に存在する可能性は否定できません。
(Javaだったら例外投げるという手もありますが)
そこで、OptinalIntの登場です。
getValue()メソッドの戻り値の型をOptionalIntに変更します。
そうすると、こんなプログラムになります。
インデックスが範囲外の場合は空の、範囲内の場合は値を保持したOptionalIntを返します。
こうすると、特定の整数値をフラグにする必要が無くなり、値の「ある・なし」が明確になります。