Optionalクラス(java.utilパッケージ)は、nullチェックを簡単化し、NullPointerExceptionの発生を未然に防ぐためのクラスです。
たとえば以下は、メンバー情報をMapで管理するUtilMemberListクラスと、これを利用するためのサンプルです。まずは、Optionalクラスを利用せずに記述してみます。
- package com.example.mynavi.util;
- import java.util.Map;
- public class UtilMemberList {
- // メンバー情報を「id: 名前」の形式で管理
- public Map<String, String> list;
- public UtilMemberList(Map<String, String> list) {
- this.list = list;
- }
- // id値をキーにメンバーの名前を取得
- public String getNameById(String id) {
- return this.list.get(id);
- }
- }
- package com.example.mynavi.util;
- import java.util.Map;
- import java.util.Optional;
- public class UtilOptBasic {
- var ml = new UtilMemberList(Map.of(
- "N-001-0A", "佐藤敏夫",
- "F-023-0B", "田中修",
- "A-104-0C", "鈴木直男"
- ));
- var name = ml.getNameById("Z-9999-0X");
- System.out.println(name.trim());
- }
- }
Map#getメソッドは、指定されたキーが存在しない場合にnullを返します。その場合に、trimメソッドをそのまま呼び出してしまうと、NullPointerException例外の原因となるわけです。
これを避けるために、Optionalクラス以前では、以下のようなnullチェックを施すのが一般的でした。
- if(name == null) {
- System.out.println("存在しません。");
- } else {
- System.out.println(name.trim());
- }
しかし、呼び出し側では戻り値にnullの可能性があるかどうかを考慮しながらコードを記述しなければならないため、漏れの原因となります。そこでOptionalクラスを利用して、getNameByIdメソッドを書き換えます。
- import java.util.Optional;
- ...中略...
- public Optional<String> getNameById(String id) {
- return Optional.ofNullable(this.list.get(id));
- }
Optional.ofNullableは、与えられた値をもとにOptional<String>オブジェクトを生成します。Optional<String>は、nullであるかもしれないStringを意味します。これを読み取るのが以下のコードです。
- import java.util.Optional;
- ...中略...
- var name = ml.getNameById("Z-9999-0X");
- System.out.println(name.orElse("存在しません。").trim());
Optional<String>オブジェクトから値を取得するには、orElseメソッドを利用します。引数は値がnullの場合に採用するデフォルト値を意味します。先ほどのifによる分岐に比べると、コードがシンプルになっていますし、なによりOptionalクラスのままでは値を利用できないので、nullチェックが強制されます。null値の可能性がある戻り値では、このようにOptionalクラスでラップすることでnull安全なコードを記述できます。
監修