オプションとは何ですか?
Optional パラメーターは、オブジェクトを運び、さまざまな API でnull参照を処理できるようにするために使用されます。コードスニペットを見てみましょう。Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Sugarオブジェクトのインスタンスから砂糖を取得するCoffeeインスタンス があります。数量値がCoffeeコンストラクターに設定されていないと仮定すると、Coffee.getSugar().getQuantity() はNullPointerExceptionを返します。もちろん、いつでも古き良きNullチェックを使用して問題を解決できます。
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
quantity = coffee.getSugar().getQuantity();
}
今はすべてうまくいっているようです。ただし、Java コードを作成する場合は、 nullチェックの実装は避けた方がよいでしょう。Optional を使用してこれを行う方法を見てみましょう。
作成方法 オプション
オプションのオブジェクトを作成するには 3 つの方法があります。-
of(T value) — オプションの非 null オブジェクトのインスタンス化。of()を使用してnullオブジェクトを参照すると、NullPointerExceptionがスローされることに注意してください。
-
ofNullable(T value) - null を指定できるオブジェクトのオプションの値を作成します。
-
empty() - nullへの参照を表す Optional インスタンスを作成します。
// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
これで、Optional オブジェクトが完成しました。次に、Optional の 2 つの主な方法を見てみましょう。
-
isPresent() - このメソッドは、Optional オブジェクトに null 以外の値が含まれているかどうかを示します。
-
get() - 現在の値を使用して Optional の値を取得します。空の Optional でget()を呼び出すとNullPointerExceptionが発生することに注意してください。
オプションによる Null チェックの改善
では、上記のコードをどのように改善できるでしょうか? Optional を使用すると、 isPresent()を使用してオブジェクトの存在を理解し、 get()を使用してそれを取得できます。まずは、isPresent()メソッドを使用して、 Coffee.getSugar()の結果をOptional でパッケージ化します。これは、 getSugar() がnull を返すかどうかを判断するのに役立ちます。Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
Sugar sugar = sugar.get();
int quantity = sugar.getQuantity();
}
この例を見ると、 coffee.getSugar() の結果をOptional にパッケージ化しても、価値が追加されるわけではなく、むしろ手間がかかるように見えます。Optional クラスのお気に入りの関数を使用することで、結果を改善できます。
-
map(Function<? super T,? extends U> マッパー) - Optional に含まれる値を指定された関数にマップします。Optional パラメーターが空の場合、map() はOptional.empty()を返します。
-
orElse(T other) は、get()メソッドの「特別な」バージョンです。Optionalに含まれる値を取得できます。ただし、空の Optional の場合は、 orElse()メソッドに渡された値が返されます。
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElse(0);
これは本当に素晴らしいことです - 少なくとも私はそう思います。ここで、空の値の場合にデフォルト値を返したくない場合は、何らかの例外をスローする必要があります。 orElseThrow(Supplier<? extends X>ExceptionSupplier) は、 Optional パラメーターに含まれる値を返すか、Optional が空の場合は例外をスローします。
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElseThrow(IllegalArgumentException::new);
ご覧のとおり、オプションにはいくつかの利点があります。
- nullチェックを抽象化する
- nullオブジェクトを処理するための API を提供します
- 宣言的なアプローチで何が達成されているかを表現できるようになります
オプションを効果的に使用する方法
私の仕事では、メソッドが「結果なし」状態を返すことができる場合、戻り値の型として Optional を使用します。私は通常、メソッドの戻り値の型を定義するときにこれを使用します。Optional<Coffee> findByName(String name) {
...
}
場合によってはこれは必要ありません。たとえば、 SugarクラスのgetQuantity()など、intを返すメソッドがある場合、結果が「数量がない」ことを表すnullの場合、メソッドは0を返す可能性があります。これを理解すると、CoffeeクラスのSugarパラメータはOptional として表現できると考えることができます。理論的にはコーヒーに砂糖を入れる必要がないため、一見するとこれは良いアイデアのように思えます。ただし、ここで、 Optional を使用しない場合について説明したいと思います。 次のシナリオでは、Optional の使用を避ける必要があります。
-
DTOなどのPOJOのパラメータ タイプとして。オプションはシリアル化できないため、POJO でオプションを使用すると、オブジェクトがシリアル化できなくなります。
-
メソッドの引数として。メソッドの引数がnullになる可能性がある場合、純粋なコードの観点からは、 Optional を渡すよりもnullを渡す方が望ましいと言えます。さらに、オーバーロードされたメソッドを作成して、null メソッド引数の欠如を抽象的に処理することができます。
-
欠落している Collection オブジェクトを表すため。Collection は空になる可能性があるため、値のない Collection を表すには、空のSetまたはListと同様に空のCollectionを使用する必要があります。
GO TO FULL VERSION