详解Optional类

详解Optional类

前言

  • 最近在看《阿里编程规范》,发现之前写过很多“糟糕”的代码,各种if,else满天飞,《规范》里给了很多方式来优化我们的代码,而Optional类很好的解决了null 值判断的问题。
  • 之前对于Java8的特性只停留在理论部分,从来没有想过在自己的代码里用过。但是最近用了Optional之后可以说是欲罢不能,简直是装杯神器,终于可以稍微“优雅”的编程了。

简介

  • 上面就说了Optional是为了解决null值判断,让我们可以避免显式的null值判断。

    我们先来看一小段“糟糕”的代码:

      public String getName(Person person){
          if(null == person){
              return "没有人";
          }
          return person.getName();  
      }

    我们再来看看用Optional优化过的代码:

     public String getName(Person person){
         return Optional.ofNullable(person).map(p -> p.getName()).orElse("没有人");        
     }

    根本不用我多说,利用Optional和lambda表达式优化后的代码变得更加的简洁和优雅。

详解

  • 结构

    我们先来看看Optional类的结构:

    在这里插入图片描述

    可以看出来其构造函数都是私有的,所以不能通过new来构建它,接下来以这张结构图为目录详细介绍一下Optional类。

  • 创建Optional对象

    Optional提供了三个静态方法来创建对象,如下所示:

    // 创建一个包装对象值为空的Optional对象
    Optional<String> opt1 = Optional.empty();
    // 创建包装对象值非空的Optional对象
    Optional<String> opt2 = Optional.of("optional");
    // 创建包装对象值允许为空的Optional对象
    Optional<String> opt3 = Optional.ofNullable(null);
  • Optional类提供方法的用法

    • get()

      • 源码:
       public T get() {
           if (value == null) {
               throw new NoSuchElementException("No value present");
           }
           return value;
       }
      • 介绍:

        返回包装对象实际值,为null抛出NoSuchElementException异常。

    • isPresent()

      • 源码:
      public boolean isPresent() {
          return value != null;
      }
      • 介绍:

        判断包装对象是否为空。这个方法要慎用,不然我们直接用null值判断不就行了。

    • ifPresent()

      • 源码:
       public void ifPresent(Consumer<? super T> consumer) {
           if (value != null)
               consumer.accept(value);
       }
      • 例:
      public void printName(Person person){
          Optional.ofNullable(person).ifPresent(p ->  System.out.println(p.getName()));
      }
      • 介绍:

        例子打印了人的姓名,这样就不用null判断啦,Optional已经帮我们做啦。

    • filter()

      • 源码:
       public Optional<T> filter(Predicate<? super T> predicate) {
           Objects.requireNonNull(predicate);
           if (!isPresent())
               return this;
           else
               return predicate.test(value) ? this : empty();
       }
      • 例子:
       public static void filterAge(Person person){
       Optional.ofNullable(person).filter( p -> p.getAge() > 18).ifPresent(p ->  System.out.println(p.getName));
       }
      • 介绍:

        例子打印了大于18岁人的名字。

    • 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));
           }
       }
      • 介绍:

        简介里的例子已经用到了这个方法,例子里会返回Optional,一个新的包装对象,而不是Optional。

    • flatMap()

      • 源码:
       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));
           }
       }
      • 介绍:

        我们对比map()方法,发现flatMap()的入参变了,所以说 map()是把结果自动封装成一个Optional,但是flatMap()需要你自己去封装 。

    • orElse()

      • 源码:
       public T orElse(T other) {
           return value != null ? value : other;
       }
      • 介绍:

        这个就比较简单了,简介的例子也用到了,就是简单的一个else判断。

    • orElseGet()

      • 源码:
       public T orElseGet(Supplier<? extends T> other) {
           return value != null ? value : other.get();
       }
      • 例子:
      public String getGender(Person person){
          return Optional.ofNullable(person).map(p -> p.getName()).orElseGet(() -> "没有人");      
      }
      • 介绍:

        orElseGet()方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值 。

    • orElseThrow()

      • 源码:
      public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
          if (value != null) {
              return value;
          } else {
              throw exceptionSupplier.get();
          }
      }
      • 例子
      public String getGender1(Person person){
          return Optional.ofNullable(person).map(p -> p.getName()).orElseThrow(() -> new RuntimeException("没有人"));      
      }
      • 介绍:

        orElseThrow()方法就跟orElseGet()方法非常相似了, 只不过要抛出异常,orElseThrow()方法主要用在包装对象值为空时需要抛出特定异常的场景 。

注意事项

  • 上面详解的时候我也提到了一些,那就是get()和isPresent()要慎用啊,这样才能让我们的代码更加的优雅,当然也有一些情况会用到,比如Optional空和非空都需要进行很多操作。反正我们得充分发挥Optional的作用,不然太浪费这个装杯神器了。
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值