optional
java8

Optionalの正しい使い方

Optional

java8で追加されたnullを処理するためのAPI。
適切に使えばnull制御のコードを綺麗に書ける。

Optionalの推奨しないメソッド(書き方)

  • isPresent()
  • get()
  • Optionalがクラス、インスタンスフィールドに使われている
  • Optionalが引数に使われている
IntelliJからの警告
/**
 * 'Optional<String>' used as type for field 'optional'
 Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter.
 Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result".
 Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not.
 */
private Optional<String> optional;

private static void test1(String str) {
    Optional optional = Optional.ofNullable(str);
    /**
     * Optional.get()' without 'isPresent()' check
     */
    optional.get();
}

private static void test1(Optional<String> optional ) {
    /**
     * Optional<String>' used as type for parameter 'optional'
     Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter.
     Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result".
     Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not.
     */
    optional.get();
}

optionalの推奨するのメソッド

public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional<T> filter(Predicate<? super T> predicate)
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

private static void test(String param) {
    Optional<String> optional = Optional.ofNullable(param);
    String value;

    // NG
    value = optional.isPresent() ? optional.get() : "null";
    // OK
    value = optional.orElse("null");

    // NG
    value = optional.isPresent() ? optional.get() : "null";
    // OK
    value = optional.orElseGet(() -> "null");

    // NG
    if (optional.isPresent()) {
        value = optional.get().toUpperCase();
    } else {
        value = "NULL";
    }
    // OK
    value = optional
        .map(String::toUpperCase)
        .orElse("NULL");
}