Java 8 を 6 か月以上使用していますが、新しい API の変更には非常に満足しています。 をいつ使用するかという点については、まだ自信がありません。 が使用できる場所ならどこでも を使用したい気持ちと、まったくOptional
を使用したくない気持ちの間で揺れ動いているようです。null
これを使用できる状況はたくさんあるようですが、それによってメリット(可読性 / null 安全性)が追加されるのか、それとも追加のオーバーヘッドが発生するだけなのかはわかりません。
そこで、いくつか例を挙げてみましたが、それが有益かどうかについてコミュニティの皆さんの意見を聞きたいですOptional
。
1 - メソッドが返すことができる場合のパブリック メソッドの戻り値の型としてnull
:
public Optional<Foo> findFoo(String id);
2 - メソッドパラメータとして、パラメータが次のようになる場合null
:
public Foo doSomething(String id, Optional<Bar> barOptional);
3 - Bean のオプション メンバーとして:
public class Book {
private List<Pages> pages;
private Optional<Index> index;
}
4 - 中Collections
:
一般的に私はそうは思いません:
List<Optional<Foo>>
filter()
何かを追加します - 特に、値などを削除するために使用できるためですが、コレクション内でnull
の適切な使用法はありますか?Optional
見逃したケースはありますか?
ベストアンサー1
の主な設計目標は、Optional
値を返す関数に、戻り値が存在しないことを示す手段を提供することです。この議論これにより、呼び出し元は一連の流れるようなメソッド呼び出しを継続できます。
これは、OP の質問の使用例#1に最も近いものです。ただし、値が存在しないことはnullよりも正確な表現です。なぜなら、 のようなものはIntStream.findFirst
null を返すことができないからです。
使用例#2では、オプションの引数をメソッドに渡しますが、これはうまく機能しますが、かなり扱いにくいです。文字列の後にオプションの 2 番目の文字列が続くメソッドがあるとします。2Optional
番目の引数として を受け入れると、次のようなコードになります。
foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());
null を受け入れるのも良いでしょう:
foo("bar", "baz");
foo("bar", null);
おそらく最善の方法は、単一の文字列引数を受け入れ、2 番目の引数にデフォルトを提供するオーバーロード メソッドを用意することです。
foo("bar", "baz");
foo("bar");
これには制限はありますが、上記のどちらよりもはるかに優れています。
ユースケース#3と#4では、クラス フィールドまたはデータ構造内に がありOptional
、これは API の誤用と見なされます。まず、これはOptional
冒頭で述べた の主な設計目標に反します。次に、これは何の価値も追加しません。
に値が存在しない場合の対処方法は 3 つありますOptional
。代替値を提供する、代替値を提供する関数を呼び出す、または例外をスローすることです。フィールドに格納する場合は、初期化時または割り当て時にこれを行います。OP が述べたように、リストに値を追加する場合は、単に値を追加しないという追加の選択肢があり、それによって存在しない値を「平坦化」します。
フィールドまたはコレクションにを格納したいという不自然なケースを思いつく人もいるかもしれませんOptional
が、一般的には、これを避けるのが最善です。