従来のヌルポインターチェックの代わりにJava 8以降でOptionalを使用する理由


110

最近、Java 8に移行しました。今、アプリケーションがOptionalオブジェクトであふれていることがわかります。

Java 8(スタイル1)より前

Employee employee = employeeServive.getEmployee();

if(employee!=null){
    System.out.println(employee.getId());
}

Java 8(スタイル2)の後

Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee());
if(employeeOptional.isPresent()){
    Employee employee = employeeOptional.get();
    System.out.println(employee.getId());
}

Optional<Employee> employeeOptional = employeeService.getEmployee();サービス自体がオプションを返すときの付加価値はありません:

Java 6のバックグラウンドから来た私は、スタイル1がより明確で、コードの行が少ないと考えています。ここに欠けている本当の利点はありますか?

すべての回答からの理解とブログでのさらなる調査から統合



28
うん!employeeOptional.isPresent()オプションタイプのポイントが完全に欠落しているようです。@MikePartridgeのコメントによると、これは推奨または慣用的ではありません。明示的なオプションの種類があるかどうかをチェックする何かまたは何もすることは一切ありません、ではありません。あなたは単純に、mapまたはflatMapそれらの上にいるはずです。
アンドレス

7
参照してくださいスタックオーバーフローが、上の回答によってブライアン・ゲッツJava言語アーキテクトオラクルで。Optional
バジルブルク

6
これは、「ベストプラクティス」の名のもとに脳をオフにすると起こります。
イミビス

9
これはオプションの使用方法がかなり悪いですが、それでも利点があります。ヌルではすべてがあなたが絶えず、この特定の変数が存在しないことを可能性があることを、オプションのコールをチェックアウトする必要があるので、nullの場合も、あなたはそれをチェックしてください
リチャード・チンクル

回答:


108

スタイル2は、Java 8を完全に活用するには十分ではありません。あなたはまったく望んでいませんif ... useOracleの例を参照してください。彼らのアドバイスを受けて、私たちは以下を得る:

スタイル3

// Changed EmployeeServive to return an optional, no more nulls!
Optional<Employee> employee = employeeServive.getEmployee();
employee.ifPresent(e -> System.out.println(e.getId()));

または、より長いスニペット

Optional<Employee> employee = employeeServive.getEmployee();
// Sometimes an Employee has forgotten to write an up-to-date timesheet
Optional<Timesheet> timesheet = employee.flatMap(Employee::askForCurrentTimesheet); 
// We don't want to do the heavyweight action of creating a new estimate if it will just be discarded
client.bill(timesheet.orElseGet(EstimatedTimesheet::new));

19
実際、isPresentのほとんどの使用は禁止されています(コードレビューで検出)
jk。

10
@jk。確かに、過負荷があった場合void ifPresent(Consumer<T>, Runnable)、私は全体の禁止を主張するだろうisPresentget
Caleth

10
@Caleth:Java 9に興味があるかもしれませんifPresentOrElse(Consumer<? super T>, Runnable)
wchargin

9
このJava 8スタイルには、Java 6スタイルと比較して1つの欠点があります。コードカバレッジツールをだます。if文では、ここではなく、ブランチを見逃したときに表示されます。
ティエリー

14
@Aaronは「コードの可読性を劇的に低下させます」。どの部分が正確に可読性を低下させますか?客観的な推論よりも、「いつも違ったやり方をしているので、習慣を変えたくない」という感じです。
Voo

47

Optionalまだ返される可能性のある古いAPI間の「互換性」レイヤーとして使用している場合、何かを持ってnullいると確信できる最新の段階で(空ではない)オプションを作成すると役立ちます。たとえば、あなたが書いた場所:

Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee());
if(employeeOptional.isPresent()){
    Employee employeeOptional= employeeOptional.get();
    System.out.println(employee.getId());
}

私はに向けて選ぶ:

Optional.of(employeeService)                 // definitely have the service
        .map(EmployeeService::getEmployee)   // getEmployee() might return null
        .map(Employee::getId)                // get ID from employee if there is one
        .ifPresent(System.out::println);     // and if there is an ID, print it

ポイントは、null以外の従業員サービスがあることを知っているため、それをwith でラップできることです。それから、あなたがそれを呼び出すとき、あなたは従業員を得るかもしれないし、そうでないかもしれない。その従業員はIDを持っている場合があります(または場合によっては持っていない場合があります)。次に、IDで終わった場合、それを印刷します。OptionalOptional.of()getEmployee()

明示的にチェックする必要はありませんいかなるなどヌル、存在が、このコードでは、。


4
(...).ifPresent(aMethod)over を使用する利点は何if((...).isPresent()) { aMethod(...); }ですか?ほぼ同じ操作を行う単なる別の構文のようです。
ルスラン

2
@Ruslanすべての場合に同等に機能する一般的なソリューションが既にあるのに、特定の呼び出しに1つの特別な構文を使用するのはなぜですか?ここでもmapとcoから同じアイデアを適用しています。
Voo

1
@Ruslan ... APIは、空のコレクションまたは配列の代わりにnullを返します。たとえば、次のようなことができます(getChildren()が子のセットを返すParentクラス、または子がない場合はnullを想定):Set<Children> children = Optional.of(parent).map(Parent::getChildren).orElseGet(Collections::emptySet); これでchildren、均一に処理できるようになりましたchildren.forEach(relative::sendGift);。これらを組み合わせることもできますOptional.of(parent).map(Parent::getChildren).orElseGet(Collections::emptySet).forEach(relative::sendGift);。ヌルチェックのすべての決まり文句など、...
ジョシュア・テイラー

1
@Ruslan ...は、標準ライブラリで試行された真のコードに委任されます。それは、など私は、プログラマーとして、記述する必要がコードの量、テスト、デバッグを減らす
ジョシュア・テイラー

1
Swiftを使用していることを嬉しく思います。let employee = employeeService.employee {print(employee.Id); }
gnasher729

23

Optional単一の値を持つ場合、付加価値はほとんどありません。これまで見てきたように、それnullはチェックをプレゼンスのチェックに置き換えるだけです。

そのようなものを持つことには大きな付加価値がありCollectionます。古いスタイルの低レベルループを置き換えるために導入されたすべてのストリーミングメソッドOptionalは、物事を理解し、それらについて正しいことを行います(処理せず、最終的に別のunsetを返しますOptional)。個々のアイテムよりも頻繁にn個のアイテムを処理する場合(そして現実的なプログラムすべての99%が処理する場合)、オプションで表示するものを組み込みでサポートすることは大きな改善です。理想的なケースではnull 存在存在を確認する必要はありません。


24
別にコレクション/ストリームから、オプション例えば、APIをより自己文書を作ることも素晴らしいですEmployee getEmployee()Optional<Employee> getEmployee()。技術的には両方が復帰nullする可能性がありますが、そのうちの1つはトラブルを引き起こす可能性がはるかに高くなります。
アモン

16
単一の値のオプションには多くの価値があります。.map()途中でnullをチェックしなくてもできることは素晴らしいことです。例えば、Optional.of(service).map(Service::getEmployee).map(Employee::getId).ifPresent(this::submitIdForReview);
ジョシュアテイラー

9
付加価値がないという最初のコメントには同意しません。オプションは、コードにコンテキストを提供します。一目で関数の正確性を確認でき、すべてのケースがカバーされます。一方、nullチェックでは、すべてのメソッドですべてのReferenceタイプをnullチェックする必要がありますか?同様のケースは、クラスおよびパブリック/プライベート修飾子に適用できます。彼らはあなたのコードにゼロの値を追加しますか?
-ArTs

3
@JoshuaTaylor正直なところ、その表現に比べて、私はの昔ながらのチェックを好んでいnullます。
キリアンフォス

2
単一の値であってもOptionalのもう1つの大きな利点は、必要なときにnullをチェックすることを忘れないことです。そうでなければ、それは...チェックを忘れると、NullPointerExceptionで終わることは非常に簡単です
ショーン・バートン

17

OptionalためisNotNull()に派手なAPIのように使用する限り、そうであれば、をチェックするだけで違いを見つけることはできませんnull

あなたが使用してはならないもののOptionalために

Optional値の存在を確認するためだけに使用するのはBad Code™です。

// BAD CODE ™ --  just check getEmployee() != null  
Optional<Employee> employeeOptional =  Optional.ofNullable(employeeService.getEmployee());  
if(employeeOptional.isPresent()) {  
    Employee employee = employeeOptional.get();  
    System.out.println(employee.getId());
}  

あなたが使うべきものOptionalのために

nullを返すAPIメソッドを使用するときに必要に応じて値を生成することにより、存在しない値を避けます。

Employee employee = Optional.ofNullable(employeeService.getEmployee())
                            .orElseGet(Employee::new);
System.out.println(employee.getId());

または、新しい従業員の作成に費用がかかりすぎる場合:

Optional<Employee> employee = Optional.ofNullable(employeeService.getEmployee());
System.out.println(employee.map(Employee::getId).orElse("No employee found"));

また、メソッドが値を返さない可能性があることをすべての人に認識させます(何らかの理由で上記のようなデフォルト値を返せない場合):

// Your code without Optional
public Employee getEmployee() {
    return someCondition ? null : someEmployee;
}
// Someone else's code
Employee employee = getEmployee(); // compiler doesn't complain
// employee.get...() -> NPE awaiting to happen, devs criticizing your code

// Your code with Optional
public Optional<Employee> getEmployee() {
    return someCondition ? Optional.empty() : Optional.of(someEmployee);
}
// Someone else's code
Employee employee = getEmployee(); // compiler complains about incompatible types
// Now devs either declare Optional<Employee>, or just do employee = getEmployee().get(), but do so consciously -- not your fault.

そして最後に、他の回答ですでに説明されているすべてのストリームのようなメソッドがありますが、それらは実際に使用することを決定するのではOptionalなく、Optional他の誰かが提供するものを使用します。


1
@Kapep確かに。この議論は/ r / javaで行われ、私は次のように言いました«私はOptional逃した機会Optionalget()Optionalget()だと思います「ここに、私が作ったこの新しいものがあるので、null値のチェックを強制されます。ああ、ところで... メソッドを追加したので、実際に何もチェックする必要はありません;);)」 。(...)は「このMIGHT BE NULL」のネオンサインとしては良いですが、そのメソッドの裸の存在はそれを不自由にします»。しかし、OPは使用する理由を求めていましたOptional。それに対する理由や設計上の欠陥ではありません。
ワレン

1
Employee employee = Optional.ofNullable(employeeService.getEmployee());3番目のスニペットでは、タイプはそうではありませんOptional<Employee>か?
チャーリーハーディング

2
@immibisどのように不自由になりましたか?使用する主な理由getは、レガシーコードを操作する必要がある場合です。新しいコードでこれまでに使用する多くの正当な理由を考えることはできませんget。つまり、レガシーコードとやり取りする場合、多くの場合、代替手段はありませんが、それでもwalenにはget初心者の存在が悪いコードを書く原因になるという点があります。
Voo

1
@immibis Map一度も言及しませんでしたし、このような劇的な非後方互換性のある変更を行っている人はOptionalいないので、悪いAPIを意図的に設計できることを確認してください-それが証明するものはわかりません。Optionalいくつかのために理にかなっているtryGetかの方法。
Voo

2
@Voo Mapは誰もが知っている例です。もちろんMap.get、後方互換性のためにオプションを返すことはできませんが、このような互換性の制約がない別のマップのようなクラスを簡単に想像できます。と言うclass UserRepository {Optional<User> getUserDetails(int userID) {...}}。ここで、ログインしたユーザーの詳細を取得します。ログインしたユーザーの詳細が存在し、システムがユーザーを削除することはありません。だからあなたはtheUserRepository.getUserDetails(loggedInUserID).get()
イミビス

12

オプションを使用する際の重要なポイントは、開発者が関数の戻り値かどうかを確認する必要があるときに明確にすることです。

//service 1
Optional<Employee> employeeOptional = employeeService.getEmployee();
if(employeeOptional.isPresent()){
    Employee employeeOptional= employeeOptional.get();
    System.out.println(employee.getId());
}

//service 2
Employee employee = employeeService.getEmployeeXTPO();
System.out.println(employee.getId());

8
オプションを備えた気の利いた機能的なものはすべて、この点よりも重要であると考えられていることは、私を困惑させます。Java 8より前は、呼び出しからの応答をnullチェックする必要があるかどうかを知るために、Javadocを掘り下げる必要がありました。Java 8以降では、戻り値の型から「何も」戻らないかどうかがわかります。
-Buhb

3
まあ、「古いコード」の問題があり、物事はまだnullを返す可能性があります...しかし、はい、署名から伝えることができるのは素晴らしいことです。
ホーコンLøtveit

5
確かに、オプションの<T>が値が欠落している可能性があることを表現する唯一の方法である言語、つまりnull ptrのない言語で確実に機能します。
dureuill

8

あなたの主な間違いは、あなたがまだより手続き的な観点から考えていることです。これはあなたを人として批判することではなく、単なる観察です。より機能的な用語で考えるには時間と練習が必要です。したがって、メソッドは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番目の大きな勝利です。これにより、より明確なコードを作成できます。また、多くのことを行うメソッドを作成して、マップにフィードできるようにすることも、一般的には良い考えだと思います。


1
ここでの問題は、これらの機能バージョンが古いバージョンと同じくらい読みやすいように聞こえるようにすることです。ある例では、例が「完全に明確」であるとさえ言います。そうではありません。この例は明確でしたが、完全にはそうではありませんでした。map(x).ifPresent(f)単純に同じ種類の直感的な意味をなさないif(o != null) f(x)ifバージョンは完全に透明です。これは、人気のあるバンドワゴンに飛び乗る人々の別のケースであり、実際の進歩のケースではありません
アーロン

1
関数型プログラミングやの使用には利点がないと言っているわけではないことに注意してくださいOptional。複数の人がこの形式のように振る舞うので、この特定のケースではオプションの使用、さらに読みやすさだけに言及していましたif
アーロン

1
それは私たちの明快さの概念に依存します。あなたは非常に良い点を述べていますが、多くの人々にとってラムダはある時点で新しくて奇妙であったことを指摘したいと思います。かなり多くの人がisPresentと言い、嬉しい安心を得るインターネットCookieをあえて賭けます。彼らは今、レガシーコードを更新し、ラムダ構文を後で学ぶことができました。一方、Lispの、Haskellのまたは類似の言語の経験を持つ人は、おそらく彼らは今、Javaで彼らの問題におなじみのパターンを適用することができることを喜んでいた...
ホーコンLøtveit

@Aaron-明確さはオプションの型のポイントではありません。私は個人的には明確さを低下させないことを発見し、(この場合ではありませんが)それを増加させる場合がありますが、主な利点は(使用を避けisPresentget現実的に可能な限り)安全性を向上させる。型がOptional<Whatever>nullableを使用するのではなく、値の不在をチェックしない不正確なコードを記述することは困難Whateverです。
ジュール

すぐに値を取り出しても、を使用しない限りget、欠損値が発生したときに何をするかを選択する必要があります:デフォルトを提供するorElse()(またはorElseGet())を使用するかorElseThrow()選択したものをスローする問題の性質を文書化する例外。これは、スタックトレースを掘り下げるまで意味のない汎用NPEよりも優れています。
ジュール

0

スタイル2には利点がありません。nullチェックが必要であることに気づく必要がありますが、今ではさらに大きくなり、読みにくくなりました。

employeeServive.getEmployee()がOptionalを返すと、コードは次のようになります。

Optional<Employee> employeeOptional = employeeServive.getEmployee();
if(employeeOptional.isPresent()){
    Employee employee= employeeOptional.get();
    System.out.println(employee.getId());
}

この方法では、employeeServive.getEmployee()。​​getId()を呼び出すことができず、オプションのバロエを何らかの方法で処理する必要があることに気付きます。また、コードベースメソッド全体でnullが返されない場合(または、このルールの例外がチームによく知られている場合はほとんどありません)、NPEに対する安全性が向上します。


12
Optionalは、使用する瞬間に意味のない複雑になりますisPresent()。オプションを使用するため、テストする必要はありません。
candied_orange

2
他の人が言ったように、使用しないでくださいisPresent()。これはオプションへの間違ったアプローチです。mapまたはflatMap代わりに使用します。
アンドレス

1
@CandiedOrangeしかも、トップ投票の回答(使用するように言っているifPresent)は、テストする別の方法です。
イミビス

1
@CandiedOrange ifPresent(x)は、と同じくらいのテストif(present) {x}です。戻り値は関係ありません。
イミビス

1
@CandiedOrangeそれにもかかわらず、あなたはもともと「テストする必要がない」と言っていました。あなたが実際にまだテストしているとき、あなたは「だから私たちはテストする必要がない」と言うことはできません...あなたはあなたです。
アーロン

0

最大の利点は、メソッドシグネチャがを返す場合、nullをチェックしないEmployeeことです。その署名によって、従業員を返すことが保証されていることがわかります。失敗のケースを処理する必要はありません。オプションで、あなたはあなたが知っています。

私が見たコードでは、nullが可能かどうかを判断するためにコードをトレースしたくないため、決して失敗しないnullチェックがあります。これにより、コードが少し遅くなりますが、さらに重要なことは、コードのノイズが大きくなることです。

ただし、これが機能するには、このパターンを一貫して適用する必要があります。


1
これを実現するためのより簡単な方法は、静的分析を使用して静的分析@Nullable@ReturnValuesAreNonnullByDefault併用することです。
maaartinus

@maaartinus静的分析の形式で追加のツールを追加し、デコレータアノテーションにドキュメントを追加しますが、コンパイル時のAPIサポートはシンプルですか?
そり

コードを変更する必要がないため、追加のツールを追加するのは確かに簡単です。さらに、とにかく他のバグもキャッチするので手に入れたいです。+++私は追加ささいなスクリプトを書いているpackage-info.java@ReturnValuesAreNonnullByDefault私のすべてのパッケージには、私がしなければならないすべては、追加することです@Nullableあなたがに切り替えていますOptional。これは、文字数が少なく、ガベージが追加されず、ランタイムのオーバーヘッドがないことを意味します。メソッドにカーソルを合わせると表示されるドキュメントを参照する必要はありません。静的分析ツールは、ミスとその後のヌル値可能性の変更を検出します。
-maaartinus

私の最大の懸念Optionalは、nullabilityに対処する代替方法が追加されることです。当初からJavaであった場合は問題ないかもしれませんが、今では苦痛です。コトリンの道を行くことは私見よりもはるかに良いでしょう。+++ List<@Nullable String>はまだ文字列のリストですが、そうでList<Optional<String>>はないことに注意してください。
maaartinus

0

私の答えは:しないでください。少なくともそれが本当に改善されているかどうかをよく考えてください。

次のような表現(別の回答から取得)

Optional.of(employeeService)                 // definitely have the service
        .map(EmployeeService::getEmployee)   // getEmployee() might return null
        .map(Employee::getId)                // get ID from employee if there is one
        .ifPresent(System.out::println);     // and if there is an ID, print it

は、元々nullを返すことができるメソッドを処理する正しい機能的な方法のようです。見栄えがよく、投げられず、「不在」のケースの処理について考えることもありません。

古いスタイルの方法よりも良く見える

Employee employee = employeeService.getEmployee();
if (employee != null) {
    ID id = employee.getId();
    if (id != null) {
        System.out.println(id);
    }
}

これにより、else条項がある場合があることが明らかになります。

機能的なスタイル

  • 見た目は完全に異なります(使用していない人には読めません)
  • デバッグするのが大変です
  • 「不在」のケースを処理するために簡単に拡張することはできません(orElse常に十分とは限りません)
  • 「不在」のケースを無視するように誤解を招く

決して万能薬として使用するべきではありません。それが普遍的に適用可能であった場合、.演算子のセマンティクスは?.演算子のセマンティクスに置き換えられるべきであり、NPEは忘れられ、すべての問題は無視されます。


Javaの大ファンである一方で、私は機能的なスタイルは文のJavaの貧しい男の代わりに過ぎないと言う必要があります。

employeeService
.getEmployee()
?.getId()
?.apply(id => System.out.println(id));

他の言語からよく知られています。この声明に同意しますか

  • (本当に)機能していない?
  • 古いスタイルのコードに非常に似ていますが、はるかに単純ですか?
  • 機能的なスタイルよりもはるかに読みやすいですか?
  • デバッガーフレンドリーですか?

あなたは、C#の記述されているように見えるの実装 Javaのとは全く異なるものとして言語機能でこの概念のを実装コアライブラリクラスを持ちます。私には同じように見えます
カレス

@キャレスまさか。「null-safe評価を単純化する概念」について話すことはできますが、私はそれを「概念」とは呼びません。Javaはコアライブラリクラスを使用して同じことを実装していると言えますが、それは単なる混乱です。で開始しemployeeService.getEmployee().getId().apply(id => System.out.println(id));、安全なナビゲーション演算子を使用して一度、それを一度使用してヌルセーフにしOptionalます。もちろん、「実装の詳細」と呼ぶこともできますが、実装は重要です。ラムダがコードをよりシンプルでより良いものにする場合がありますが、ここでは単なるい虐待です。
-maaartinus

ライブラリクラス:Optional.of(employeeService).map(EmployeeService::getEmployee).map(Employee::getId).ifPresent(System.out::println);言語機能:employeeService.getEmployee()?.getId()?.apply(id => System.out.println(id));。2つの構文が、彼らは見て終わる非常によく似た私に。「概念」はOptional別名Nullable別名Maybe
カレス

なぜこれらの1つが「ugい虐待」であり、他の1つが良いと考えるのか理解できません。私はあなたが両方とも「ugい虐待」または両方良いと思っているのを理解できました。
カレス

@Caleth 1つの違いは、2つの疑問符を追加する代わりに、すべてを書き直す必要があることです。問題は、言語機能とライブラリクラスコードが大きく異なるということではありません。それで大丈夫です。問題は、元のコードとライブラリクラスのコードが大きく異なることです。同じアイデア、異なるコード。それは残念です。+++悪用されるのは、ヌル値を処理するためのラムダです。Lamdasは大丈夫ですが、そうでOptionalはありません。Nullabilityには、Kotlinのような適切な言語サポートが必要です。別の問題:List<Optional<String>>に関係List<String>ありませんが、それらを関連付ける必要があります。
-maaartinus

0

オプションは、関数型プログラミングに由来する概念(高次型)です。これを使用すると、ネストされたnullチェックがなくなり、運命のピラミッドからあなたを救います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.