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言語の時代は)、こんな風に書かれていたと思います。

f:id:MasatoshiTada:20140725171705p:plain

getValue()メソッドは、インデックスが配列の範囲外だった場合のフラグとして、-1を返しています。

このコードの弱点は、getValue()メソッドが-1を返した時に、インデックスが配列の範囲外だったのか、指定したインデックスに本当に-1という値があったのかが、判定できないことです。

じゃあ-1じゃなくて別の値(例えば-1000とか)にすりゃあいいじゃんとも思いますが、それでも、その値が配列内に存在する可能性は否定できません。

Javaだったら例外投げるという手もありますが)

 

そこで、OptinalIntの登場です。

getValue()メソッドの戻り値の型をOptionalIntに変更します。

そうすると、こんなプログラムになります。

f:id:MasatoshiTada:20140725174657p:plain

インデックスが範囲外の場合は空の、範囲内の場合は値を保持したOptionalIntを返します。

こうすると、特定の整数値をフラグにする必要が無くなり、値の「ある・なし」が明確になります。