Java でクラスのフィールドのNULLチェックとかして、というか、Java 8 で導入されたStreamとラムダ式の絡みで、NullPointerException を回避したいじゃないっすか...どうもボクです。
Java 8 で導入された、Optionalっちゅうものを使ってイケるらしいと。
そして、ぜんぜん関係ないけど、
⇧ 衝撃...
なぜ「うるう日」が「逆プロポーズの日」になったのでしょうか?
1288年、スコットランドのマーガレット女王は、
「未婚の女性はうるう年ごとに、好きな男性に対してプロポーズすることができる。男性がプロポーズを拒むには、罰金を払うか、絹のドレスを与えなければならない」という法律を制定しました。
これではさすがに、うるう年の一年の間ずっと、プロポーズを拒めないことになりますので反発も多く、その後、うるう日のみに改訂されました。
同じような法律はフランスにもあり、15世紀にはイタリアでも慣習になっていました。
⇧ 4年に一度か...オリンピックとおんなじか~...でも、願わくば男性版の法律も作って欲しいところです
というわけで、Optional ってどう使うの?ってな部分を調査していきますか~。レッツトライ~。
Optionalとは?
まずは、Javadocの説明を見てみますか。
クラスOptional<T>
- java.lang.Object
-
- java.util.Optional<T>
public final class Optional<T> extends Object
null以外の値が含まれている場合も含まれていない場合もあるコンテナ・オブジェクトです。値が存在する場合、isPresent()
はtrue
を返し、get()
は値を返します。含まれる値の有無に応じて追加メソッドが提供されます。たとえば、
orElse()
(値が存在しない場合にデフォルト値を返す)、ifPresent()
(値が存在する場合にコードのブロックを実行する)など。これは値ベースのクラスで、
Optional
のインスタンスに対して、ID依存操作(参照等価性(==
)、IDハッシュ・コード、同期など)を使用すると、予期できない結果になる可能性があり、避けてください。- 導入されたバージョン:
- 1.8
⇧ サッパリですな...コンテナ・オブジェクトって何のこっちゃ?
Wikipediaさんによりますと、
コンピュータプログラミングにおいて、コンテナとはオブジェクトの集まりを表現するデータ構造、抽象データ型またはクラスの総称である。コレクションとも言う。コンテナには複数の種類があり、それぞれ独自の方法でオブジェクトを組織的に格納する。
よく知られたものには、
などがある。
⇧ ってなってるけど、こういう認識で良いってことですかね?
何かを入れて運ぶクラス。
いくつかの意味がある。
「コレクションクラス」のことを指す場合。
クラスの中に各クラスを「格納」できるため、ArrayListクラス等のコレクションクラスを「コンテナクラス」と呼ぶ場合がある。
そのものずばり、Containerクラスというものも存在する。
ContainerクラスはAWTのクラスのひとつで、ウィンドウを表示する場合に、ボタン等を入れる「枠」となるクラスである。ウィンドウを表示するWindowクラスもこのContainerクラスのサブクラスである。
Webアプリケーションを実行するためのクラスも「コンテナクラス」と呼ばれる。
サーブレットを実行するクラスを「サーブレットコンテナ」、JSPを実行するクラスを「JSPコンテナ」と言う。また、それらを総称して、アプリケーションサーバーそのものを「サーブレット/JSPコンテナ」「Webコンテナ」もしくは単に「コンテナ」と言うこともある。
このように、様々な意味を持つ単語のため、どの意味かは文脈から読み取る必要があるため注意。
⇧ 上記サイト様によりますと、文脈から読み取れとありますね...javadoc の説明だとまったく読み取れんけど...まぁ、「Optional<T>」ってなってるから、T にはどんなものでも入るって認識で大丈夫なんでしょうかね...
Optional の使い方については、
⇧ 上記サイト様が詳しいです。
Java界隈の著名人であられる、きしださんも、
⇧ かなり、早い時期に Optional について言及されてますね。2013年って...あっしは、まだパソコンに触れたことがない時代ですね...
んで、きしださんのブログで、Optional のモナドについての議論が紹介されてました。海外の勇気ある人が、Javaの中の人にリクエストしたことにより、「map」「flatMap」のメソッドが実装されたそうな...
Optional はメソッドの戻り値として使うらしい
らしいっす。
なんか、自分でクラスとか作成してたら、そのクラスのメンバーメソッドなんかで戻り値が、Optional<T> なものを用意しておいてあげないといけないらしい。
アンチパターンとしては、
⇧ 上記サイト様で紹介されてるのですが、少なくとも、
- Optional Types in Object Fields
- Collections of Optionals
- Optional as a Method Argument
- Trying to Serialize Optionals
の4つの使用法はNGらしいっす。
4つ目については、
In case you really, really need to serialize Optional, you have to consider using different libraries, like Guava Optional or Vivr Optional.
⇧ 「どうしてもシリアライズなOptional を実装したいなら、外部APIのGoogle GuavaやVivrのOptional を使え」って言ってますね、っていうか「Vivr」ってのが何なのか分からん...Vavr(旧:Javalang) ってのは存在するらしいけど。
というか、コレクションで使ったらアカンって...Optionalの流儀がよく分からんですな...
- Do not declare any instance variable of type Optional.
- Use null to indicate optional data within the private scope of a class.
- Use Optional for getters that access the optional field.
- Do not use Optional in setters or constructors.
- Use Optional as a return type for any other business logic methods that have an optional result.
Stephen Colebourne's blog: Java SE 8 Optional, a pragmatic approach
⇧ きしださんが、Optional の使いどころを紹介してくれてました。
⇧ Lombok とか使ってる場合、Optional ってどうすれば良いのやらですね...
⇧ 上記サイト様によりますと、やはり相性が良くないみたいですね...
Optional を使ってみる
んで、やりたいことは、クラスのフィールドが入れ子のオブジェクトになってるようなパターンのnull チェックですよね~、っていうことで、
You can use Optional.flatMap
here
employee.getHuman()
.flatMap(Human::getMale)
.flatMap(Male::getAge)
.ifPresent(age -> System.out.println("I discovered the variable finally " + age);
Java 8 Optional - how to handle nested Object structures - Stack Overflow
⇧ 上記サイト様で、「Optional.flatMap」使ったらいけますぜ、と。
ただ、これ、質問者の方のクラスの作りが、インスタンスフィールドにOptional 付けたり、メソッドの引数にOptional 付けたり、アンチパターンを使いまくってる...
⇧ なんか、Oracleさんも普通に、アンチパターンやってますね...
改善が必要とは言ってるし、Google Guvnaでも似たようなことやってるって言ってる風なんだけど、Googleもおんなじような問題を抱えてるんじゃない?的なことを暗に言わんとしてるのか...相変わらず、Oracle適当ですな...
最早、正解が分からない...
2014年3月の内容なので今は改善されてるのか分からんけども、少なくともそういう情報は出てこないけども...調べ方が悪いとは思うけど...
2019/5/18(土)に、
⇧ JJUG(Japan Java User Group)のイベントがあるので、行った時に聞いてみますかね...
差し当たっては、アンチパターンと言われてるもので実装するしかなさそうですね...
んで、実装してみて、くそハマった...
⇧ 上記サイト様と同じ状況かな~、と思ったんだけども、Optional.flatMapの使い方を普通に間違ってました...。
Eclipseを起動し、適当なJavaプロジェクト、クラスを作成で。
今回は、
⇧ ちょっとクラスが多くなったので、ソースコードをGitHub にアップしました。
一応、プロジェクトの構成は、下記画像で。
まぁ、何ていうか、Optional 使い方が難しい...っていうか結局、良く分からん...
flatMap とかも良く分からんし...
Streamに関してのflatMapについては、
⇧ 上記サイト様が詳しいです。
Stream と Optional の flatMap の比較については、
⇧ 上記サイト様が詳しいです。
きしださんも仰てましたが、「モナド」について
⇧ 上記サイト様が説明してくれていました。
覚えなきゃならんことが多すぎて...いっぱいいっぱいです...
今回はこのへんで。