Optional 进阶使用

Optional 中的方法:

  1. Optional.empty()
  2. Optional of(obj)
  3. Optional ofNullable(obj)
  4. public T get()
  5. public boolean isPresent()
  6. public T orElse(T other)
  7. public T orElseGet(Superlier<? extends T> other)
  8. public void ifPresent(Consumer<? super T> consumer)
  9. public <U> Optional<U> map(Function<? super T, ? extends U> mapper)
  10. public Optional<T> filter(Predicate<? super T>) predicate
  11. public <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
  12. public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws x

注意:每一个被调用的方法都只对他前面的结果负责


(1)Optional.empty()

三种构造方式之一:

重新new一个Optional(),并返回

源码:

    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    private static final Optional<?> EMPTY = new Optional<>();

(2)Optional.of(obj)

三种构造方式之一:

将数据 转换成 Optional类型(获取具有指定类型的指定值的Optional类的实例)
要求传入参数非空,否则会报NullPointerException
可通过 .get()方法 获取原值

源码:

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

应用场景:

  1. 非常明确 将要传给 Optional.of(obj) 的 obj 参数不可能为 null 时
    比如obj是一个刚new出来的对象,或者是一个非null常量。
     
  2. 想为 obj 断言非 null 时
    比如 想要 obj 一旦为 null 就立即报告 NullPointerException 异常, 而不是隐藏

(3)Optional.ofNullable(obj)

三种构造方式之一:

功能与Optional.of()相同,底层也应用了Optional.of()方法。
但是对 null 类型进行了判断,如果为null,则方法内部会 通过 Optional.empty()方法重新 new 一个新的空的 Optional进行返回

源码:

    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

(4)get()

获取调用对象原有值

调用对象为空,则直接返回报错 NoSuchElementException() 信息为 No value present

源码:

    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

注意:

没有 isPresent() 作铺垫的 get() 调用在 IntelliJ IDEA 中会收到告警

Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception.

调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常


(5)isPresent()

判断当前对象是否存在,返回 boolean 值

本质上 isPresent() 与 obj != null 无任何分别

源码:

    public boolean isPresent() {
        return value != null;
    }

应用:

假定已有一个实例 Optional<User> user

boolean flag = user.isPresent();

(6)orElse()

存在即返回, 不存在则提供默认值

调用对象非空,则返回该对象

调用对象为空,则返回指定值

源码:

    public T orElse(T other) {
        return value != null ? value : other;
    }

应用:

import org.junit.Test;

import java.util.Optional;


public class OptionalAdvanced {

    public final String nullStr = null;
    public final LocalBean localBean = null;


    @Test
    public void testOrElse() {

        // 可以 替换 nullStr.isPresent() ? nullStr : "user orElse() print content";
        String ofNullableStr = Optional.ofNullable(nullStr).orElse("user orElse() print content");
        System.out.println(ofNullableStr);

        // 可以替换 localBean.isPresent() ? localBean.get() : new LocalBean();
        LocalBean localBean = Optional.ofNullable(this.localBean).orElse(new LocalBean());
        System.out.println(localBean);
    }
}

(7)orElseGet()

存在即返回,不存在则由函数来产生

源码:

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

应用:

import org.junit.Test;

import java.util.Optional;


public class OptionalAdvanced {

    @Test
    public void testOrElseGet() {
        LocalBean backBean = Optional.ofNullable(this.localBean).orElseGet(() -> this.giveBean());
        System.out.println(backBean);
    }

    public LocalBean giveBean() {
        return new LocalBean();
    }
}

(8)ifPresent(Consumer<? super T> consumer)

存在才对它做点什么

源码:

    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

应用:

import org.junit.Test;

import java.sql.SQLOutput;
import java.util.Optional;


public class OptionalAdvanced {

    public final LocalBean localBean = null;


    @Test
    public void testIfPresent() {
        // 可替换此类型的判断代码
        //if (user.isPresent())
        //    System.out.println(user.get());

        Optional<LocalBean> fullBean = Optional.ofNullable(new LocalBean());
        fullBean.ifPresent(System.out::println);

        Optional<LocalBean> nullBean = Optional.ofNullable(this.localBean);
        nullBean.ifPresent(System.out::println);
    }
}

(9)map() 函数

获取对象中的某个字段的值

源码:

    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));
        }
    }

应用:

import org.junit.Test;

import java.sql.SQLOutput;
import java.util.Locale;
import java.util.Optional;


public class OptionalAdvanced {

    public final String nullStr = null;
    public final LocalBean nullBean = null;


    @Test
    public void testMap() {
        // 对象为空
        LocalBean nullBean = null;
        String there_is_no_name = Optional.ofNullable(nullBean).map(bean -> bean.getName()).orElse("there is no name");
        System.out.println(there_is_no_name);   // there is no name

        // 属性为空
        LocalBean emptyBean = new LocalBean();
        String this_is_empty_bean = Optional.ofNullable(emptyBean).map(bean -> bean.getName()).orElse("there is no name");
        System.out.println(this_is_empty_bean); // there is no name

        // 对象、属性 均非空
        LocalBean fullBean = new LocalBean();
        fullBean.setName("kobe");
        Optional<LocalBean> fullBeanOptional = Optional.ofNullable(fullBean);

        String here_has_name = fullBeanOptional.map(bean -> bean.getName()).orElse("there is no name");
        System.out.println(here_has_name);      // kobe

        // 调用其他函数
        fullBeanOptional.map(bean -> bean.getName()).ifPresent(System.out::println);   // kobe

        // map 可能无限级联的, 比如再深一层, 获得用户名的大写形式
        String upperCase = fullBeanOptional.map(bean -> bean.getName()).map(name -> name.toUpperCase(Locale.ROOT)).orElse("there is no name");
        System.out.println(upperCase);      // KOBE
    }
}

Groovy 提供了一种安全的属性/方法访问操作符

 ?.

应用:

user?.getUsername()?.toUpperCase();

Swift 也有类似的语法, 只作用在  Optional 的类型上.


(10)filter()

把不符合条件的值变为 empty()

源码:

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

应用:

    @Test
    public void testFlatMap() {

        // 对象、属性 均非空
        LocalBean fullBean = new LocalBean();
        fullBean.setAge(22);
        Optional<LocalBean> fullBeanOptional = Optional.ofNullable(fullBean);

        LocalBean fullBack = fullBeanOptional.filter(bean -> bean.getAge() == 22).orElse(new LocalBean());
        System.out.println(fullBack);      // LocalBean(age=22, name=null, address=null)

        LocalBean emptyBack = fullBeanOptional.filter(bean -> bean.getAge() > 22).orElse(new LocalBean());
        System.out.println(emptyBack);      // LocalBean(age=null, name=null, address=null)
    }

(11)flatMap()

总是与 map() 方法成对的,

map中获取的返回值自动被Optional包装,即  返回值 ----> Optional<返回值>

flatMap中返回值保持不变,但必须是Optional类型,即Optional<返回值> -> Optional<返回值>

参考:https://www.cnblogs.com/lijingran/p/8727149.html

源码:

    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

应用:

    @Test
    public void testFlatMap() {
        // 对象、属性 均非空
        LocalBean fullBean = new LocalBean();
        fullBean.setAge(22);
        Optional<LocalBean> fullBeanOptional = Optional.ofNullable(fullBean);
        Optional<Integer> integer = fullBeanOptional.flatMap(OptionalAdvanced::getOrderNumber);
        System.out.println(integer);
    }
    private static Optional<Integer> getOrderNumber(LocalBean fullBean) {
        return Optional.ofNullable(fullBean).map(bean -> bean.getAge());
    }

(12)orElseThrow()

有值时直接返回, 无值时抛出想要的异常

源码:

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

应用:

    @Test
    public void testOrElseThrow() {
        // 对象、属性 均非空
        LocalBean nullBean = null;
        Optional<LocalBean> nullBeanOptional = Optional.ofNullable(nullBean);
        LocalBean xinxicuowu = nullBeanOptional.orElseThrow(() -> new RuntimeException("xinxicuowu"));
        System.out.println(xinxicuowu);
    }

总结:

使用 Optional 时尽量不直接调用 Optional.get() 方法, Optional.isPresent() 更应该被视为一个私有方法, 应依赖于其他像 Optional.orElse()Optional.orElseGet()Optional.map() 等这样的方法.

Optional 的方法中基本都是内部调用  isPresent() 判断, 真时处理值, 假时什么也不做.


声明:

转自:Java8 Optional 的正确使用方式 - 简书

其他大神更细致的讲解:https://www.cnblogs.com/lijingran/p/8727149.html
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值