今回は
- orElse
- orElseGet
- orElseThrow
について勉強しました。
orElse
Optional が値を持っている場合はその値を、空の場合は渡された値を返します。
Optional<String> opt = Optional.of("non-null");
System.out.println(opt.orElse("null"));
// non-null
Optional<String> opt = Optional.empty();
System.out.println(opt.orElse("null"));
// null
前回のまとめ言ってたこの例ですが、
String s = opt.isPresent() ? opt.get() : "default text";
orElse を使うとこう書けます。
String s = opt.orElse("default text");
orElseGet
Optional が値を持っている場合はその値を返します。空の場合は渡されたコードブロックを実行し、コードブロックが返した値を返します。
Optional<String> opt = Optional.of("non-null");
System.out.println(opt.orElseGet(() -> "null"));
// non-null
Optional<String> opt = Optional.empty();
System.out.println(opt.orElseGet(() -> "null"));
// null
orElseThrow
Optional が値を持っている場合はその値を返します。空の場合は例外を返すコードブロックを実行し、例外を Throw します。
Optional<String> opt = Optional.of("non-null");
System.out.println(opt.orElseThrow(java.lang.IndexOutOfBoundsException::new));
// non-null
Optional<String> opt = Optional.empty();
System.out.println(opt.orElseThrow(java.lang.IndexOutOfBoundsException::new));
// Exception in thread "main" java.lang.IndexOutOfBoundsException
orElse と orElseGet の違い
上記のように、orElse
は引数をそのまま返しのに対して orElseGet
はコードブロックが返す値を返します。orElse
だけで良くない?と思うかもしれませんが、orElseGet
には次のような利点があります。
それは、「コードブロックは Optional が空の場合しか実行されない」点です。
import java.util.Optional;
public class Test {
public static void main(String[] args) {
Optional<String> opt = Optional.of("non-null");
String v = opt.orElseGet(() -> {
// このコードブロックは実行されない。
fn1();
return "default value";
});
System.out.println(v);
}
private static void fn1() {
System.out.println("fn1 start.");
}
}
// non-null
コードブロックでラップするため、empty 時に返す値の取得を遅延評価できます。キャッシュがあればそれを使うけどない場合は DB から取得する、というようなケースに便利そうです。