2015-12-24 7 views
9

これはJava 8でのオプションの有効な使用方法ですか?Java 8でのオプションの有効な使用方法

class Foo { 
     private final Integer id; 
     private final String name; 
     private final String countryCode; 

     Foo(final Integer id, final String name, final String countryCode) { 
      this.id = id; 
      this.name = name; 
      this. countryCode = countryCode; 
     } 

     public String getName() { 
      return name; 
     } 

     public String getCountryCode() { 
      return countryCode; 
     } 
    } 

    class FooSrv { 
     private Optional<Foo> getFoo(final Integer id) { 
      return id != null && id == 1 ? Optional.of(new Foo(id, "Bar", "US")) : Optional.empty(); 
     } 

     private boolean isFooValid(final Integer id) { 
      return getFoo(id) 
       .filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode()))   
       .map(f -> true) 
       .orElse(false); 
     } 
    } 
+0

質問:なぜ-1ですか? –

+0

'.map(f - > true)。orElse(false);'は '.isPresent()'と言っても分かりません。 –

+0

それは意味しませんでした。もし存在していれば、他のオブジェクトを返すということは、別のオブジェクトを返すということです。ブールはおそらく私の例では最善の選択ではなかった –

答えて

17

私はこれで別の振る舞いをします。

これは有効な使用ですか?はい、狭い意味では、あなたが期待している結果をコンパイルして生成します。

この使用目的ですか?いいえ。今、時には本来の目的を超えて有用性が見いだされることもあります。しかし、Optionalについては、通常はうまくいかないことがわかりました。

Brian Goetzと私はJavaOneの2015年の話でOptionalの問題のいくつかを議論し、Javaの8ラムダでAPIの設計とストリーム

主にOptionalの使用は以下の通りである(スライド36)

オプションを表していないために明確な必要性がある場合、「何の結果は、」図書館法戻り値の型ため限定メカニズムを提供することを目的とし、そのためにnullを使用しているエラーの原因と圧倒的そうです。

Optionalからメソッドをチェーン化する能力は間違いなく非常に涼しく、場合によっては条件付きロジックからのクラッタを減らします。しかし、かなり頻繁にこれはうまくいかない。典型的なコードのにおいはそれは連鎖方式へ順に、NULL可能だと条件を避けるために何かからOptionalを作成し、代わりにハンドルいくつかのメソッドから返さOptionalにメソッドチェーンを使用してコードの、あります。

// BAD 
String process(String s) { 
    return Optional.ofNullable(s).orElseGet(this::getDefault); 
} 

// GOOD 
String process(String s) { 
    return (s != null) ? s : getDefault(); 
} 

Optionalを用いる方法が長く、ほとんどの人は、従来のコードよりもそれがより曖昧見つける:ここでのアクションでその例だ(また、私たちのプレゼンテーションから、42をスライドさせます)。それだけでなく、正当な理由がないため余分なゴミを作ります。

ボトムライン:あなたはでき何かをするという理由だけで、あなたがそれをを行う必要があることを意味するものではありません。

+0

最初の建設的な答え。ありがとうございました!私の質問は非常に妥当だとは思うが、非常に大規模に下降していた。私はそれを言い換えるべきか? –

+0

@ŁukaszRzeszotarskiありがとうございました。 downvotesについて何をすべきかを言うのは難しい。 downvotes(およびクローズド・ボート)はおそらく、質問が意見に基づいている、またはあなたがディスカッション/議論を探していると感じる人々から来るでしょう。それは避けてください。しかし、私はこの特定の質問について何をすべきか分かりません。 –

+0

@StuartMarks **オプションは、返された値が存在しない可能性を表すために、API(インターフェイスまたはクラスのパブリックメソッド)で非常に有用です。 'public interface OrderService {Optional findOrderWithId(long id);}'では、戻り値の型は 'Order'が存在しないかもしれないと言っています。クライアントコードでは、 'null'命令を処理することを忘れる機会が減り、潜在的な' NullPointerException'の機会が少なくなります。詳細:[オプションを使用して不在を指定する](http://praveer09.github.io/technology/2015/09/19/using-optional-to-specify-presence-or-absence-of-a-value/) –

2

その少し不自然が、「有効」(「構文上」のように)、しかし@yshavitがに指摘したように、それは、ライブラリの開発で使用するために意図されていました。


以前の回答は、FPコードが読みにくいためでした。以下はコメントです(少し冗長ですが、javadocのコメントであるb/cですが)。 IMHOを読むのがはるかに簡単です。 (第二には、コメントはありません、と読みやすさを助けるために、少なくともアライメント)

private boolean isFooValid(final Integer id) { 
    return getFoo(id) 
     // filter if 'f' matches the predicate, return Optional w/f if true, empty Optional if false 
     .filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode())) 
     // If a value is present, apply the provided mapping function to it, 
     // If non-null, return an Optional describing the result. 
     .map(f -> true) 
     // Return the value if present, otherwise return other. 
     .orElse(false); 
} 

あるいは、少なくともラインそれをため、その詳細上で何が起こっているかを明白にし、読みやすいです。

private boolean isFooValid(final Integer id) { 
    return getFoo(id) 
     .filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode())) 
     .map(f -> true) 
     .orElse(false); 
} 
+0

間違っていると思います。 'getFoo(int)'が空の 'Optional'を返すと、' filter'はラムダの一部である 'getName()'を呼び出さないからです。 – ajb

+0

「フィルタ」を指摘した後に更新されました。私が最初に見たときに、その単語を見ていなかったのですか:/ – mawalker

4

それが「有効」だかどうかを尋ねるという意見に基づくが、それはユースケースを意図したのかどうかのようである:いいえ、そうではありません。

OracleのJava言語アーキテクトであるBrian Goetzは、「値なし」マーカーが必要な場合は、and when using null for this is likely to cause errorsというオプションを使用すると述べています。具体的には、メソッドの妥当なユーザーが結果がnullである可能性を考慮していない場合は、オプションを使用する必要があります。明示的にはではありませんでした。は、ここで使用しているように、一般的な「多分」タイプのオブジェクトを意図しています。

あなたの場合、オプションを返すメソッドはprivateです。つまり、クラスの実装者のみが使用でき、クラスのメソッドについてよく知っていると仮定することができます。それらのメソッドのどれが返されるかなど、nullが返されます。混乱の妥当なリスクはないので、Brian Goetzはこれを有効なユースケースとは考えない(おそらく)と言っています。

+0

それは公共の方法だったらあなたの答えは「はい」でしょうか? –

+0

@ŁukaszRzeszotarski答えは「それは依存する」でしょう。具体的には、nullを返すだけで「エラーを引き起こす可能性が圧倒的に高い」と思われるかどうか(Goetzの回答から引用したものです)。これは、このコードスニペットでは判断できない判断の呼び出しです。 – yshavit

+0

この文はちょっと混乱していると思います。「OracleのJava言語アーキテクトであるBrian Goetzは、「値なし」マーカーが必要な場合は「オプション」の使用例を示し、NULLを使用するとエラーが発生する可能性があると述べています。 'もしBrian Goetz氏の間でスタックオーバーフローが発生することなくAPIの使用が明確になるようにapiが設計/文書化されれば素晴らしいだろう。しかし、私が理解しているように、あなたの意見は、null値を返すことになっているパブリックメソッドに対してのみ意味があるということです。 –

6

これは、多かれ少なかれ意見・ベースの質問ですので、私は中に地雷を投げるよ。あなたは

if (id == 1) { 
    Foo f = new Foo(id, "Bar", "US"); 
    return "Bar".equals(f.getName()) && "US".equals(f.getCountryCode()); 
} else { 
    return false; 
} 

を言おうとしている場合は、ちょうどそれを言います。物事を「機能的」にすることは、物事を自動的にはっきりさせるものではなく、不要なコードを導入することで、コードをより複雑にして理解するのが難しくなりました。私は、Javaの設計者が、人々がOptionalを使用してコードをよりわかりにくくすることを意図しているとは考えていません。

EDIT:いくつかの回答を読んだ後、いくつかのコメントを追加する価値があると思います。これは私がよく知っている関数型プログラミングイディオムではなく、理解するのが難しくなります。イディオムI によく慣れ親しんでおり、Javaストリーム、または配列やリストの複数の値、または複数の値の他のコレクションに適用された(他の言語の)機能イディオムがほとんどです。そのような場合には、不慣れを過ぎると、関数の構文は、いくつかの詳細を隠すことができる(ループインデックス、イテレータ、実行ポインタ、アキュムレータ変数)ことができるため、改善と見なすことができます。全体的に見れば、事を単純化することができます。この例だけでは、このような単純化は行われません。

ただし、Optionalの機能の一部は、ストリームのコンテキストで役立ちます。 parseInt()メソッドがOptional<Integer>を返し、入力文字列が無効な場合は空であるとします。 (Java 8は本当にこれを提供しているはずです。)これにより、文字列の配列を取得し、解析されない文字列が結果から単に除外される整数配列を生成することが容易になります。parseIntをストリームmap()で使用し、ストリームフィルタを使用して除外します空のOptionalを入力します。 (私はこれを行う方法を尋ねる複数のStackOverflowの質問を見てきました)ストリームフィルタを使用する前にOptional.filter()を使用して非正規表現をOptional.empty()に変更することができます(この場合、後で別のストリームフィルタを使用しますが、より複雑な場合はOptionalフィルタを使用する方が便利です)。これは、機能的な観点から、Optionalの主な利点として私が見ているものです。これは、値の集合を一度に扱うことを可能にし、 "非値"を表現する方法を提供し、それでも機能する関数を書くことができます。ですから、Optionalの主な用途は、nullの代わりに、シーケンス全体に関数を適用している間に、一連の値に空白を代入することです。

+0

原則として私は同意しません。あなたはいくつかの構文に慣れているので読みやすいと思います。私にとって、両方の可読性は同じです。しかし、デザイナーが別の目的のために作ったときに、そのように使うべきではないというyhsavitに同意します。 –

+0

私はyshavitに同意したと言いましたが、可能な場合はnullを返す可能性のあるパブリックメソッドのみを使用することになっています。しかし、別の問題はフィルタ構文です。あなたはそれが好きではありません。 Irなぜそれが公開されているのですか?結論としては、オプションの型はJava 8での使用が非常に限定されており、実際には多くの人が思うほど大きな特徴ではありません。 –

+0

回答を編集して回答しました。 – ajb

関連する問題