JavaのOptionaとは?使い方をパターン別にわかりやすく解説


JavaのOptionalって何?
Optionalの使い方を詳しく知りたい

OptionalはJava8から追加されたクラスです。Optionalクラスを使うと値がnullであるかどうかチェックする記述を簡潔に書くことができます。

そのため、記述量が減ってシンプルな表記にできることがメリットです。この記事では、Optionalクラスについて、基本的な使い方から応用的な使い方まで網羅的に解説していきます。

この記事はこんな人のために書きました。

  • JavaのOptionalが何か知っておきたい
  • JavaのOptionalについて使い方を詳しく知りたい

今回はJavaのOptionalについて詳しく見ていきましょう。

なお、Javaの記事については、こちらにまとめています。

目次

JavaのOptionalとは?

Javaでは値のない状態のことをnullと言いますが、開発中はnullが原因で意図しないエラーが発生することも多いです。そのため、エラーを未然に防ぐためにnullチェックの処理を書く必要がありました。

多くの場合はif文を使って変数内の値がnullかどうか確認します。しかしOptionalを使うと、値がnullであるかどうかを簡潔に書くことができます。if文のブロックを書かなくてもnullチェックが記述できるため、ifをネストさせることも極力避けて書くことができます。

またはっきりと「値が入っていない場合」という処理を示すことがでるため、ifによるnullチェック時のミスを減らすことも可能になり、プログラムの堅牢性も向上すると思われます。

このOptionalはjava.util.OptionalクラスのことでJava8から導入されています。現時点(2018/6)でのバージョンはJava10ですが、Java9、Java10でもメソッドの追加、変更が実施されています。

Java10の環境構築方法についてはこちらで詳しく解説していますので、ぜひ参考にしてください。

JavaのOptionalの使い方

Optionalの書き方

Optionalクラスを使うには、java.util.Optionalをインポートする必要があります。Optionalクラスは一般的に以下のようにオブジェクトを定義して使用します。

Optional<T> オブジェクト名 = Optional.ofNullable(nullの可能性があるオブジェクト名);

Optionalのオブジェクトはダイヤモンド演算子(<>)内のType Parameterにnullの可能性があるオブジェクトの型を指定して宣言します。OptionalのオブジェクトにはofNullableメソッドの戻り値を代入します。

ofNullableメソッドの引数にはnullの可能性があるオブジェクト名を指定します。ofNullableメソッドは引数がnullの場合に、Optional型の空のオブジェクトを返します。

引数がnull以外の場合は、指定された値を記述するOptional型のオブジェクトを返します。例えば以下のように記述します。

String str = null;
Optional<String> value = Optional.ofNullable(str);

ofNullableメソッドの戻り値を使って処理を行う方法については、このあと詳しく解説していきます。

orの使い方

orメソッドの使い方について説明します。orメソッドはOptional.ofNullableメソッドの引数に指定したオブジェクトがnullの場合のみ処理を実行します。

orメソッドの戻り値の型はOptional型です。それではサンプルコードで確認しましょう。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        System.out.println(value.or(() -> Optional.of("nullです")).get());
    }
 
}

実行結果:

nullです

このサンプルコードではorメソッドの引数をラムダ式で記述しています。Optionalクラスのメソッドの引数にはラムダ式を指定することもできます。

ここではOptional.ofNullableメソッドの引数がnullですので、処理が実行されます。ofメソッドを使って文字列「nullです」を記述するOptional型のオブジェクトを返します。さらにgetメソッドを使って、文字列の値を取得しています。

ラムダ式の記述方法については、こちらで詳しく解説していますので、ぜひ参考にしてください。

orElseの使い方

まずはサンプルコードで使い方をみてみましょう。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        str = value.orElse("strはnullです");
        System.out.println(str);
    }
 
}

実行結果:

strはnullです

このサンプルコードではOptional型のオブジェクトからorElseメソッドを呼び出しています。Optional.ofNullableメソッドの引数がnullの場合にorElseメソッドの引数の値を返します。

nullでない場合はnullでないその値を返します。

orElseThrowの使い方

orElseThrowメソッドは引数なしと引数ありの場合で処理が異なります。

引数なしの場合

引数なしのorElseThrowメソッドはJava10で追加されました。orElseThrowメソッドはnullの場合はNoSuchElementExceptionをスローします。

nullでない場合は値を返します。

import java.util.NoSuchElementException;
import java.util.Optional;
 
public class OptionalSample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        try {
            str = value.orElseThrow();
            System.out.println(str);
        } catch (NoSuchElementException ex) {
            System.out.println("nullです");
        }
    }
}
nullです

このサンプルコードでは、Optional.ofNullableメソッドの引数がnullですので、orElseThrowメソッドでNoSuchElementExceptionの例外がスローされています。

引数ありの場合

引数ありのorElseThrowメソッドはJava8より使用可能でした。orElseThrowの引数には例外をスローする例外クラスのオブジェクトを指定することができます。

import java.util.Optional;
 
public class OptionalSample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        try {
            System.out.println(value.orElseThrow(() -> new RuntimeException()));
        } catch (RuntimeException e) {
            System.out.println("nullです");
        }    
    }
}

実行結果:

nullです

streamの使い方

streamメソッドを使うと、nullチェックをせずにOptional型のオブジェクトからnullでないものだけを取り出すことができます。

ちなみに、streamメソッドはJava9から追加されています。

import java.util.List;
import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        List<String> list1 = List.of("Tokyo", "Osaka");
        List<String> list2 = null;
        
        Optional<List<String>> value1 = Optional.ofNullable(list1);
        Optional<List<String>> value2 = Optional.ofNullable(list2);
        
        value1.stream().flatMap(x -> x.stream()).forEach(System.out::println);
        value2.stream().flatMap(x -> x.stream()).forEach(System.out::println);
    }
    
}

実行結果:

Tokyo
Osaka

List型のオブジェクトlist1はnullではないので、streamメソッドで要素を取得できています。一方list2の場合はnullであるにもかかわらず、エラーは発生ぜずに処理を実行できています。

ifPresentの使い方

ifPresentメソッドはnullでない場合のみ引数に指定した処理を行います。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        value.ifPresent(System.out::println);
    }
 
}

このサンプルコードではifPresentメソッドを使っていますが、文字列型の変数strがnullであるため処理は行われません。str = nullの部分を例えばstr = “abc”と変えることで実行するとabcと表示されるようになります。

ifPresentOrElseの使い方

ifPresentOrElseメソッドはJava9より追加されました。ifPresentOrElseメソッドではnullの場合も処理を行うことができるようになっています。

nullでない場合の処理を第1引数に指定します。nullの場合の処理を第2引数に指定します。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        value.ifPresentOrElse(
            System.out::println, 
            () -> System.out.println("nullです"));
    }
 
}

実行結果:

nullです

まとめ

ここでは、Java8から追加になったOptionalの使い方について説明しました。Optionalを使うと、値がnullであるかどうかチェックする記述を簡潔に書くことができます。

if文のブロックを書かなくてもnullチェックが記述できるため、ifをネストさせることも極力避けて書くことができます。慣れて使いこなせることができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
info@sss-lab.com

目次