JavaのOptionalでnullを意識しないプログラムを作る方法

プログラミング

プログラムはできるだけシンプルに分かりやすく記述することで、バグや認識違いを少なくすることができます。

JavaのOptionalは、nullを意識しないプログラムにすることができ、バグの発生を少なくできる手法の1つです。

本記事では、JavaのOptinalでnullを意識しないプログラムを作る方法について解説します。

記事内に記載しているプログラムは、Java11を使って動作確認をしています。

JavaのOptionalでnullを意識しないプログラムを作る方法

JavaのOptionalについて、以下の内容を解説します。

  • Optionalとは
  • Optionalの生成方法
  • Optionalからの値の取得方法
  • Optionalを使った処理方法

Optionalとは

Optionalは、java.util.Optionalクラスのことで、Java8より追加された機能です。
文字列や数値、オブジェクトを値として保持し、またその値がnullであるかもしれないことを表現するクラスです。

通常はメソッドの戻り値として使われる場合が多い機能となります。
これまで処理結果の値、もしくはnullを返していた戻り値をOptionalにすることによって、「値をもっていないかもしれない」ということを呼び出し側に伝えることができます。

呼び出し側は、戻り値に対してif文によるnullチェックを行わなくても安全に処理が出来るようになることがメリットとなります。
以下は従来とOptionalを使った場合の例です。

// 従来はメソッドの戻り値がnullでないことをチェックしていた
String result1 = getValue();
if (result1 == null) {
    System.out.println(result1);
}

// Optionalを使うと戻り値がある場合のみ処理することが出来る
String result2 = getValue();
result2.ifPresent(System.out::println);

Optionalの生成方法

Optionalクラスは、newによって作成することが出来ないクラスです。
代わりに生成するためのメソッドが3種類用意されています。

emptyは値のないOptionalを生成します。
nullを戻り値として返す場合は、このemptyでOptionalを生成して返すようにします。

Optional v1 = Optional.empty();

ofはnullが入ってはいけない場合に使います。
ofにnullを指定すると例外が発生します。

Optional v2 = Optional.of("value");

ofNullableは、値が入るかもしれないし、nullかもしれない場合に使います。
通常はこれを使うことが多くなると思います。

Optional v3 = Optional.ofNullable("value");

Optionalからの値の取得方法

Optionalから値を取得する方法として、3種類の方法があります。

getは、Optionalの値を取得します。値がない場合(nullである場合)は、例外が発生します。
値が入っていることが保証されている、またはnullの場合は処理が続行できない場合などに使用します。

Optional v2 = Optional.of("value");
System.out.println(v2.get()); // -> value

orElseは、値が存在する場合はその値を返し、値がない場合は指定した値を返します。

Optional v1 = Optional.empty();
System.out.println(v1.orElse("Java")); // -> Java

Optional v2 = Optional.of("value");
System.out.println(v2.orElse("Java")); // -> value

orElseGetは、値が存在する場合はその値を返し、値がない場合は処理した結果を返します。
orElseとの違いは、値がない場合の処理を行うことができる点になります。

Optional v1 = Optional.empty();
System.out.println(v1.orElseGet(() -> "Java")); // -> Java

Optional v3 = Optional.ofNullable("value");
System.out.println(v3.orElseGet(() -> "Java")); // -> value

Optionalを使った処理方法

Optionalを使った処理は、用途に応じて様々な方法が提供されています。

値の存在を確認する方法

isPresentは、値が存在する場合はtrue、存在しない場合はfalseを返します。

Optional v2 = Optional.of("value");
System.out.println(v2.isPresent()); // -> true

Optional v1 = Optional.empty();
System.out.println(v1.isPresent()); // -> false

逆にisEmptyは、値が存在する場合はfalse、存在しない場合はtrueを返します。

Optional v2 = Optional.of("value");
System.out.println(v2.isEmpty()); // -> false

Optional v1 = Optional.empty();
System.out.println(v1.isEmpty()); // -> true

値が存在する場合だけ処理する方法

ifPresentは、値が存在する場合は指定した処理を行い、存在しない場合は何もしません。

Optional v1 = Optional.empty();
v1.ifPresent(System.out::println); // 処理されない

Optional v2 = Optional.of("value");
v2.ifPresent(System.out::println); // -> value

値が存在しない場合にも処理したい場合は、ifPresentOrElseを使用します。
第1引数に値が存在する場合の処理、第2引数に値が存在しない場合の処理を指定します。

Optional v1 = Optional.empty();
v1.ifPresentOrElse(System.out::println,
    () -> System.out.println("値が存在しない")); // -> 値が存在しない

Optional v2 = Optional.of("value");
v2.ifPresentOrElse(System.out::println,
    () -> System.out.println("値が存在しない")); // -> value

ifPresentやifPresentOrElseは、両方とも処理した結果を返すことができないメソッドです。

値がある時だけ処理をして結果を返す方法

mapは、値が存在する場合だけ指定した処理を行い、結果を返します。
戻り値は自動的にOptional型となります。

Optional v2 = Optional.of("value");
System.out.println(v2.map(s -> s.length())); // -> Optional[5]

2つのOptionalを同時に処理したい場合は、flatMapを使います。
戻り値はOptional型で、自分でOptionalオブジェクトを作成する必要があります。

Optional v2 = Optional.of("value");
Optional v3 = Optional.ofNullable("value");

System.out.println(v2.flatMap(s1 -> v3.flatMap(s2 -> {
    return Optional.of(s1 + s2);
}))); // -> Optional[valuevalue]

条件に一致する場合にOptionalを取得する方法

filterは、指定した条件に一致する場合にそのOptionalを返し、一致しない場合は値を持たないOptionalを返します。

Optional v2 = Optional.of("value");
System.out.println(v2.filter(s -> s.equals("value"))); // -> Optional[value]
System.out.println(v2.filter(s -> s.equals("Java"))); // -> Optional.empty

値のストリームを作成して処理する方法

streamは、値のストリームを作成します。
Optionalの値がリストなどの場合に有用です。

Optional<List> arr = Optional.of(Arrays.asList("Java", "Python", "Ruby"));
arr.stream().flatMap(v -> v.stream()).forEach(System.out::println); // -> Java -> Python -> Ruby

まとめ

JavaのOptionalについてまとめると、以下となります。

  • Optionalは、文字列や数値、オブジェクトを値として保持し、またその値がnullであるかもしれないことを表現するクラスである。
  • メソッド呼び出し時の戻り値が、nullかどうかをチェックする必要がなく、プログラムを安全に作ることができる。
  • Optionalを使った様々な処理方法が提供されている。

nullを返す場面がある際には、Optionalを使ってみることをおすすめします。

 

今回は、JavaのOptionalでnullを意識しないプログラムを作る方法について解説しました。

以上、参考になれば幸いです。

コメント

タイトルとURLをコピーしました