JavaSE8 Goldへの道(Upgrade to Java SE 8 Programmer 1Z0-810 試験対策)9回目です。
一連の記事は「JavaSE8Gold」ラベルを付けていきます。
今回は
一連の記事は「JavaSE8Gold」ラベルを付けていきます。
今回は
Optional
クラスです。Optional<T>クラス
java.util.Optional<T>
クラスは、nullかもしれない値を格納するコンテナクラスです。Optionalインスタンスの生成
コンストラクタは利用できません。必ずファクトリメソッドを使います。
//空のOptionalを生成 Optional<String> str = Optional.empty(); //nullでない値で生成 //※nullを渡すとNullPointerException Optional<String> optStr = Optional.of("test"); //nullかもしれない値で生成 String str = null; Optional<String> optStr = Optional.ofNullable(str);
2つめの
Optional#of
メソッドでは、nullを渡すとNullPointerException
がスローされます。したがって基本は
empty
かofNullable
メソッドで生成することになると思います。Optionalから値の取得
値の取得はいろいろな方法があります。
//単に取得 //※中身がnullだとNoSuchElementException String str = op.get(); //nullの場合渡した値を返す String str = op.orElse("default"); //nullの場合渡したラムダ式(Supplier)の結果を返す String str = op.orElseGet(() -> "default"); //nullの場合渡したラムダ式(Supplier)が返す例外をスローする String str = op.orElseThrow(() -> new RuntimeException("ぬるぽ"));
1つ目はもし中身がnullの場合
2つ目の
3つ目の
(例えば文字列連結などをする場合、nullのときしか評価されないのでパフォーマンスへの影響が少なくなります)
4つ目の
NoSuchElementException
がスローされるので、あまり出番はないと思います。2つ目の
orElse
メソッドはnullを指定することもできます。3つ目の
orElseGet
メソッドではラムダ式を渡せるので、もっと複雑な生成ロジックやを使うことができます。(例えば文字列連結などをする場合、nullのときしか評価されないのでパフォーマンスへの影響が少なくなります)
4つ目の
orElseThrow
は中身がnullの場合なにか別の例外をスローしたい場合に使えます。その他判定など
他に判定用のメソッドもあります。
//中身が存在するかどうか boolean present = op.ifPresent(); //中身が存在する場合、ラムダ式(Consumer)を実行する op.isPresent(s -> System.out.println(s));
1つ目の
ifPresent
メソッドは要するにobj != null
と同じなので、Optional
を使う意味がありません。したがって2つ目の
isPresent
メソッドが最も基本の使い方になると思います。なにかメソッドを設計したときに、nullが返される可能性がある場合は
Optional
型にしておくと、使う側で工夫が可能になります。・・・とはいえ、JavaAPIでも全てのnullを返す可能性があるメソッドが
Optional
に置き換わったわけではないので、まだまだnullチェックが全く必要なくなったわけではありません。Streamのような操作
※ここから先は試験範囲外かもしれません。
Optional
にはStream
と同じメソッドもいくつか定義されています。//値の置き換え(map) Optional<String> optStr = Optional.ofNullable("value"); Optional<Integer> optInt = optStr.map(s -> s.length()); //値の置き換え+ラップの解除(flatMap) //なにか処理をしてOptional型を返すfuncメソッドを呼ぶ Optional<String> optStr = Optional.ofNullable("value"); Optional<String> optStr2 = optStr.flatMap(s -> func(s)); //値のフィルタリング(filter) Optional<String> optStr = Optional.ofNullable("value"); Optional<String> optStr2 = optStr.filter(s -> s.startWith("a"));
全て中身が存在する場合のみラムダ式が実行されます。存在しない場合空の
より詳しくは以下の記事がわかりやすいです。
Optional
が返されるだけです。Optional#flatMap
はStream
も同じなのですが、ラムダ式の結果二重にラップされてしまう(Optional<Optional<T>>
になってしまう)場合に、ラップを1つ解除してくれます。Optional#filter
はフィルタリングの結果falseになった場合は空のOptional
になります。Stream
の終端操作にはOptional
を返すものがいくつかありますが、これらのメソッドを使うとそのまま延長した処理のように書くことができます。Optional
はStream
の要素が0または1のものとも言えなくもない、と誰かが書いてた気がします。より詳しくは以下の記事がわかりやすいです。
プリミティブ用Optional
Optional
にもプリミティブ型に対応したものが用意されています。OptionalInt
OptionalLong
OptionalDouble
get
メソッドだけ異なり、getAsXxx
となっています。前述の通り使う機会はないと思いますが。また、nullがないため
プリミティブ型
ofNullable
メソッドがありません。プリミティブ型
Stream
の終端操作の一部で戻り値として使われています。と、い、う、わ、け、で
メソッドの戻り値としてnullの可能性があるケースでは積極的に使っていきたいですね。
今後追加されるAPIでも使われると思うので、どのような操作があるかは覚えておきましょう。
今後追加されるAPIでも使われると思うので、どのような操作があるかは覚えておきましょう。
今回も以下のサイトとGoldの通常試験の参考書を参考にしています。