JDK OPTIONAL

章节方法名JDK版本备注
创建Optional对象of()8创建一个Optional
ofNullable()8上下两者的结合体,推荐使用
empty()8空的Optional
获取Optional对象orElse8为不为空都会被调用
orElseGet8区别在于只有等到为空的时候才调用 (推荐)
orElseThrow8为空抛出异常
消费Optional的值ifPresent8对象参数赋值
ifPresentOrElse9
管道化Optionalmap8一一映射
filter8过滤器
flatMap8

1. 创建Optional对象

方法名JDK版本备注
of()8创建一个Optional
ofNullable()8上下两者的结合体,推荐使用
empty()8空的Optional

注意:区别在于of()使用null创建直接报错,ofNullable()使用null等价于empty()

public class MyOptionalTest {
    @Test
    public void test05(){
        Optional<String> optionalS = Optional.of("Hello");
        Optional<String> optional = Optional.ofNullable("Hello");
        Optional<Object> empty = Optional.empty();
    }
}

2. 获取Optional对象

方法名JDK版本备注
orElse8为不为空都会被调用
orElseGet8区别在于只有等到为空的时候才调用 (推荐)
orElseThrow8为空抛出异常
public class MyOptionalTest {
    @Test
    public void test01(){
        Optional<String> str = Optional.of("Hello");
        String s = str.orElse("w");
        System.out.println(s);
        String s1 = str.orElseGet(() -> "");
        String s2 = str.orElseThrow(IllegalStateException::new);
    }
}

3. 消费Optional的值

可以用于对象的赋值操作

方法名JDK版本备注
ifPresent8
ifPresentOrElse9
public class MyOptionalTest {
    @Test
    public void test02(){
        Optional<String> str = Optional.of("Hello");
        str.ifPresent(System.out::println);
        str.ifPresentOrElse(System.out::println, ()->{employee.setName("")});
    }
}

4. 管道化Optional

方法名JDK版本备注
map8一一映射
filter8过滤器
flatMap8

其中flatMap本质上和Map相同,源码上只是进行了一次Optional包裹

public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent()) {
        return empty();
    } else {
        return Optional.ofNullable(mapper.apply(value));
    }
}
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent()) {
        return empty();
    } else {
        @SuppressWarnings("unchecked")
        Optional<U> r = (Optional<U>) mapper.apply(value);
        return Objects.requireNonNull(r);
    }
}

可以看出两者本质上是相同的,在这里不同于Stream中的map和flatMap

public class MyOptionalTest {
    @Test
    public void test03(){
        Optional<String> str = Optional.of("Hello");
        Optional<String> s = str.filter(s1 -> s1.length() > 1).map(String::toUpperCase);
        Optional<Integer> optional = Optional.of(-1);
        Optional<Double> optionalDouble = optional.flatMap(i -> i < 0 ? Optional.empty() : Optional.of(Math.sqrt(i)));
        Optional<Double> aDouble = optional.map(i -> i < 0 ? null : Math.sqrt(i));
    }
}

5. 不推荐的方式处理Optional

不合理的方式处理Optional

  1. Optional.of(null); 会出现报错
  2. 不推荐之间使用get方法获取参数
    Optional.empty() or Optional.ofNullable() 直接get() 会报错
    if(optional.isPresent) optional.get() 并不会变得简约
    JDK10将get方法称之为orElseThrow()

推荐使用的策略

1.. Optional 永远不要为null Optional<User> user = null;

  1. 不要使用Optional的域 在类的内部使用null表示更加易于操作
  2. 不要在集合中放置Optional对象,更不要将Optional作为map其中的键,而是应该直接获得对应的值

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://quguai.cn/archives/jdkoptional