0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Optionalクラスについて

Last updated at Posted at 2023-06-22

Optionalクラスとは?

メソッドの処理結果を扱うためのクラスです。
処理結果の正常・異常にかかわらず同じ型を扱うことができます。
Java SE 8で導入されました。

導入の背景

従来、メソッドの設計時には、処理結果に異常があれば例外をスローするようにしていました。この異常時の処理によって、突然catchブロックに制御が遷移するので、コードの可読性を下げていました。Optionalクラスの導入によって、例外処理に関するコードを減らすことができ、その結果コードの可読性を上げることができるようになりました。

改善例

以下はOptionalクラス導入前のソースです。このソースには課題が4つあります。

  1. インデックスが、配列の要素数を超えてしまうことがある
  2. 配列の要素がnullである可能性があるため、戻り値を受け取った側でnullの確認をしなければNullPointerExceptionが発生する
  3. 引数の配列が参照型であるため、配列への参照ではなくnullが渡される可能性がある
  4. スローされてくるIllegalArgumentExeptionは非検査例外あるため、例外処理が無視される可能性がある
public class OldTest {
  public static void main(String[] args) {
    try {

      // 課題1の箇所
      String result = getFromArray(new String[]{"A", "B", null}, 3};
      // 課題2の箇所
      if (result == null) {
        System.out.println("empty");
        return;
      }
      System.out.println(result);
    } catch (IllegalArgumentException e) {
      System.out.println("exception");
    }
  }
  // 課題3の箇所
  private static <T> T getFromArray(T[] array, int index) {
    if (array == null) {
      throw new IllegalArgumentException();
    }
    try {
      return array[index];
    } catch (ArrayIndexOutOfBoundsException e) {
      // 課題4の箇所
      throw new IllegalArgumentException();
    }
  }
}

Optionalクラスを利用して、上記のコードを以下のように改善できます。

import java.util.Optional;

public class Test {
  public static voi main(String[] args) {
    Optional<String> result = getFromArray(new String[]{"A", "B", null}, 3};
      if (result.isEmpty()) {
        System.out.println("empty");
        return;
      }
      System.out.println(result.get());
  // 課題4の改善: 例外ではなく戻り値を戻すため、例外処理そのものが不要
  private static <T> Optional<T> getFromArray(T[] array, int index) {
    if (array == null) {
      // 課題3の改善: nullチェックを行い、からのOptionalのインスタンスへの参照を戻す
       return Optional.empty();
    }
    try {
      // 課題2の改善: ofNullableメソッドは引数の値がnullだった場合、空のOptionalのインスタンスへの参照を戻す
       return Optional.ofNullable(array[index]);
    } catch (ArrayIndexOutOfBoundsException e) {
      // 課題1の改善: 例外が発生した時は空のOptionalのインスタンスへの参照を戻す
       return Optional.empty();
    }
  }
}

メソッド一覧

インスタンスを生成する

メソッド 説明
empty() 空のOptionalのインスタンスを生成し、参照を戻す
of(T value) null以外の値を持ったOptionalのインスタンスを生成し、参照を戻す
nullを渡すとNullPointerExceptionが発生する
ofNullable(T value) 値が有るか、nullの場合は、空のOptionalのインスタンスを生成し、参照を戻す

値を取得する

メソッド 説明
get() 値が有る場合はその値を、それ以外の場合はNoSuchElementExceptionをスローする

値の有無を確認する

メソッド 説明
isPresent() 値が有る場合はtrue、無い場合はfalseを戻す
isEmpty() 値が無い場合はtrue、有る場合はfalseを戻す

値を加工する

メソッド 説明
map(Function<? super T,? extends U> mapper) 値が有る場合は、引数に渡してラムダ式を実行して、その結果を持ったOptionalを戻す
flatMap(Function super T,Optional> mapper) 値が有る場合は、引数に渡してラムダ式を実行し、値が無い場合は場合は空のOptionalを戻す

値の有無で別々の処理をする

メソッド 説明
orElse(T other) 値が有る場合はその値を、無い場合は引数で渡した代替値を戻す
orElseGet(Supplier<? extends T> other) 値が有る場合はその値を、無い場合は引数のラムダ式を実行してその結果を戻す
ifPresent(Consumer<? super T> consumer) 値が有る場合は、引数に渡してラムダ式を実行する
ifPresentOrElse(Consumer super T> action, Runnable emptyAction) 値が有る場合は、第1引数で指定したラムダ式を実行し、値が無い場合は第2引数で指定したラムダ式を実行する

参考文献

徹底攻略Java SE 11 Gold問題集

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?