0%

Optional

  • 我们在编写代码的时候出现最多的就是空指针异常。所以在很多情况下我们需要做各种非空的判断。例如:

    1
    2
    3
    4
    Author author = getAuthor();
    if(author != null){
    System.out.println(author.getName());
    }
    • 尤其是对象中的属性还是对象的情况下,这种判断会更多。过多的判断语句会让我们的代码显得臃肿不堪。

    所以在 JDK8 中引入了 Optional,养成使用 Optional 的习惯后你可以写出更优雅的代码来避免空指针异常。并且在很多函数式编程相关的 API 中也都用到了 Optional,如果不会使用 Optional 也会对函数式编程的学习造成影响。

3.Optional

3.1 概述

  • 我们在编写代码的时候出现最多的就是空指针异常。所以在很多情况下我们需要做各种非空的判断。例如:

    1
    2
    3
    4
    Author author = getAuthor();
    if(author != null){
    System.out.println(author.getName());
    }
    • 尤其是对象中的属性还是对象的情况下,这种判断会更多。过多的判断语句会让我们的代码显得臃肿不堪。

    所以在 JDK8 中引入了 Optional,养成使用 Optional 的习惯后你可以写出更优雅的代码来避免空指针异常。并且在很多函数式编程相关的 API 中也都用到了 Optional,如果不会使用 Optional 也会对函数式编程的学习造成影响。

3.2 使用

3.2.1 创建对象

ofNullable
  • Optional 就好像是包装类,可以把我们的具体数据封装 Optional 对象内部,然后我们去使用 Optional 中封装好的方法操作封装进去的数据就可以非常优雅的避免空指针异常

  • 我们一般使用 Optional 的静态方法 ofNullable 来把数据封装成一个 Optional 对象,无论传入的参数是否为null都不会出现问题。 (常用)

    1
    2
    3
    Author author = getAuthor();
    Optional<Author> authorOptional = Optional.ofNullable(author);
    authorOptional.ifPresent(auyhor -> System.out.println(author.getName()));
    • 你可能会觉得还要加一行代码来封装数据比较麻烦。但是如果改造下 getAuthor 方法,让其的返回值就是封装好的 Optional 的话,我们在使用时就会方便很多。

      在这里插入图片描述

    • 而且在实际开发中我们的数据很多是从数据库获取的。Mybatis 从 3.5 版本可以也已经支持 Optional 了。我们可以直接把 dao 方法的返回值类型定义成 Optional 类型,MyBastis 会自己把数据封装成 Optional 对象返回,封装的过程也不需要我们自己操作。

  • 如果你确定一个对象不是空的则可以使用 Optional 的静态方法 of 来把数据封装成 Optional 对象。

    1
    2
    Author author = new Author();
    Optional<Author> authorOptional = Optional.of(author);
  • 如果一个方法的返回值类型是 Optional 类型,而如果我们经判断发现某次计算得到的返回值为 null,需要把 null 封装成 Optional 对象返回,这时就可以使用 Optional 的静态方法 empty 来进行封装。

    1
    Optional.empty()
  • 实际上,阅读 Optional 的源码会发现,Optional 的静态方法 ofNullable 就是静态方法 of 和静态方法 empty 的组合

    1
    2
    3
    4
    // Optional#ofNullable
    public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
    }

3.2.2 安全消费值

ifPresent
  • 我们获取到一个 Optional 对象后肯定需要对其中的数据进行使用。这时候我们可以使用其 ifPresent 方法对来消费其中的值。这个方法会判断其内封装的数据是否为空,不为空时才会执行具体的消费代码。这样使用起来就更加安全了。

    例如,以下写法就优雅的避免了空指针异常。

    1
    2
    Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
    authorOptional.ifPresent(author -> System.out.println(author.getName()));

3.2.3 安全获取值

orElseGet、orElseThrow
  • 如果我们想获取 Optional 内部的数据,可以使用 get 方法获取,但是不推荐。因为当 Optional 内部的数据为空的时候会出现异常。

    • 如果我们期望安全的获取值,推荐使用 Optional 提供的 orElseGetorElseThrow 方法。
  • orElseGet:获取数据并且设置数据为空时的默认值。如果数据不为空就能获取到该数据。如果为空则根据你传入的参数来创建对象作为默认值返回。

    1
    2
    3
    4
    5
    Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
    //无参
    Author author1 = authorOptional.orElseGet(() -> new Author());
    //有参,默认值为有参的参数
    Author author2 = authorOptional.orElseGet(() -> new Author(作者对象));
  • orElseThrow:获取数据,如果数据不为空就能获取到该数据。如果为空则根据你传入的参数来创建异常抛出。

    1
    2
    3
    4
    5
    6
    Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
    try {
    Author author = authorOptional.orElseThrow(() -> new RuntimeException("数据为null"));
    } catch (Throwable t) {
    t.printStackTrace();
    }
---------------The End---------------