あなたの主な間違いは、あなたがまだより手続き的な観点から考えていることです。これはあなたを人として批判することではなく、単なる観察です。より機能的な用語で考えるには時間と練習が必要です。したがって、メソッドはisPresentであり、最も明らかな正しい呼び出しのように見えます。二次的な小さな間違いは、メソッド内でOptionalを作成することです。Optionalは、何かが値を返す場合と返さない場合があることを文書化するのに役立ちます。何も得られないかもしれません。
これにより、完全に合理的と思われる完全に読みやすいコードを作成できましたが、getおよびisPresentである下劣な双子の誘惑に魅了されました。
もちろん、質問はすぐに「なぜ存在し、そこに到達するのか」になります。
ここで多くの人が見逃しているのは、isPresent()はgosh-darnの有用なラムダがどれほど機能的で機能的なものが好きなのかを完全に理解している人々によって書かれた新しいコードのために作られたものではないということです。
ただし、いくつかの(2つの)良い、素晴らしい、魅力的な(?)メリットがあります。
- 新しい機能を使用するためのレガシーコードの移行が容易になります。
- Optionalの学習曲線を容易にします。
最初のものはかなり単純です。
次のようなAPIがあるとします。
public interface SnickersCounter {
/**
* Provides a proper count of how many snickers have been consumed in total.
*/
public SnickersCount howManySnickersHaveBeenEaten();
/**
* returns the last snickers eaten.<br>
* If no snickers have been eaten null is returned for contrived reasons.
*/
public Snickers lastConsumedSnickers();
}
そして、あなたはこれを使用してレガシークラスを持っていました(空白を埋める):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
確かに不自然な例。しかし、ここで我慢してください。
Java 8がリリースされ、私たちは急いで乗ろうとしています。そのため、私たちが行うことの1つは、古いインターフェイスをOptionalを返すものに置き換えたいということです。どうして?他の誰かがすでに優雅に述べているように:
これは何かがnullになる可能性があるかどうかの推測を取り除きます
これはすでに他の人によって指摘されています。しかし今、問題があります。想像してみてください(無実のメソッドでalt + F7を押している間、すみません)、このメソッドがよくテストされたレガシーコードで呼び出され、それ以外の場合は素晴らしい仕事をする46の場所。次に、これらすべてを更新する必要があります。
これはisPresentが輝くところです。
なぜなら今:Snickers lastSnickers = snickersCounter.lastConsumedSnickers(); if(null == lastSnickers){新しいNoSuchSnickersException()を投げます; } else {consumer.giveDiabetes(lastSnickers); }
になる:
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
そして、これはあなたが新しい後輩に与えることができる簡単な変更です。彼は何か便利なことをすることができ、同時にコードベースを探索することができます。ウィンウィン。結局のところ、このパターンに似たものがかなり普及しています。そして今、ラムダなどを使用するためにコードを書き直す必要はありません。(この特定の場合、それは些細なことですが、読者への演習としてそれが難しい場合の例を考えてみましょう。)
これは、その方法が本質的に、コストのかかる書き換えを行わずにレガシーコードを処理する方法であることを意味していることに注意してください。では、新しいコードはどうでしょうか?
まあ、あなたの場合、あなたが何かを印刷したいだけなら、あなたは単にそうするでしょう:
snickersCounter.lastConsumedSnickers()。ifPresent(System.out :: println);
これは非常に単純で、完全に明確です。ゆっくりと表面まで泡立っている点は、get()とisPresent()のユースケースが存在するということです。それらは、既存のコードを機械的に変更して、新しいタイプをあまり考慮せずに使用できるようにするためのものです。したがって、あなたがしていることは、次のように見当違いです。
- nullを返す可能性のあるメソッドを呼び出しています。正しい考えは、メソッドがnullを返すことです。
- ラムダファンシーネスを含むおいしい新しいメソッドを使用する代わりに、レガシーの絆創膏メソッドを使用してこのオプションを処理しています。
Optionalを単純なnull安全性チェックとして使用したい場合は、次のようにする必要があります。
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
もちろん、この見栄えの良いバージョンは次のようになります。
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
ちなみに、それは決して必要ではありませんが、読みやすくするために、操作ごとに新しい行を使用することをお勧めします。曜日を問わず、ビートの簡潔さを読み、理解しやすい。
これはもちろん、私たちがやろうとしていることすべてを理解するのが簡単な非常に単純な例です。実生活では必ずしもこれが単純なわけではありません。しかし、この例では、私たちが表現しているのは私たちの意図であることに注意してください。従業員を取得し、IDを取得し、可能であれば印刷します。これはOptionalの2番目の大きな勝利です。これにより、より明確なコードを作成できます。また、多くのことを行うメソッドを作成して、マップにフィードできるようにすることも、一般的には良い考えだと思います。