• 【函数式编程】Optional接口


    概述

    在编写代码的时候遇到最多的就是空指针异常,在很多情况下都要进行很多的非空判断;

    如:

    
    	Author author = getAuthors();
        	if(author != null){
              System.out.println(author.getName());
            }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    尤其是对象中的属性还是一个对象的情况下,这种判断会更多。
    过多的非空判断会让代码变得臃肿不堪;
    JDK8中引入了Optional,使用Optional可以用更优雅的代码避免空指针异常;

    使用

    创建对象

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

    • 一般使用Optional静态方法ofNullable来把数据封装成一个Optional对象,无论传入的参数是否为null都不会出现问题;
      Author author = new Author();
      Optional authorOptional = Optional.ofNullable(author);
    
    • 1
    • 2

    看起来多加一行代码去封装数据比较麻烦,但是如果改造下getAuthor方法让其的返回值就是封装好的Oprional的话,在获取数据时就方便很多;

    在实际开发时很多数据就是从数据库中获取的,Mybatis从3.5版本之后也支持Optional了,可以直接把dao方法的返回值类型定义为Optional类型,Mybatis会自己把数据封装成Optional对象返回,封装的过程也不需要自己操作;

    • 如果确定一个对象不是空的则可以使用Optional静态方法of把数据封装成Optional对象;
      Author author = new Author();
      Optional<Author> author1 = Optional.of(author);
    
    • 1
    • 2
    • 如果一个方法的返回值是Optional类型,而如果经过判断发现某次计算得到的返回值是null,这个时候需要把null封装成Optional对象返回,可以使用Optional的静态方法empty来进行封装;
      Optional.empty();
    
    • 1

    安全消费值

    获取到一个Optional对象之后肯定需要对其中的数据进行使用,这之后可以使用ifPresent方法来消费其中的值。

    这个方法会判断其内封装的数据是否为空,不为空时才会执行具体的消费代码。

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

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

    获取值

    若想获取值自己进行处理可以使用get方法获取,但是并不推荐。因为当Optional内部的数据为空的时候会出现异常。

    安全获取值

    若想安全的获取值,不推荐使用get方法,而是使用Optional提供的以下方法

    • OrElseGet
      获取数据并且设置数据为空时的默认值,若数据不为空就能获取到该数据,若数据为空则根据传入的参数来创建对象作为默认值返回;
      Optional<Author> authorOptional1 = Optional.ofNullable(getAuthor());
      Author author = authorOptional1.orElseGet(() -> new Author());
    
    • 1
    • 2
    • OrElseThrow

    获取数据,若数据不为空就能获取到该数据,若为空则根据传入的参数来创建异常并抛出;

      Optional<Author> authorOptional2 = Optional.ofNullable(getAuthor());
      try {
         Author author1 = authorOptional2.orElseThrow((Supplier<Throwable>) () ->
         new RuntimeException("author为空"));
      } catch (Throwable throwable) {
          throwable.printStackTrace();
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    过滤

    可以使用filter方法对数据进行过滤,如果原本是有数据的,但是不符合判断条件,也会变成一个无数据的Optional对象

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

    判断

    可以使用isPresent方法进行是否存在数据的判断,如果为空返回值是false,如果不为空,返回值是true。但是这种方式并不能体现Optional的好处,更推荐使用ifPresent方法;;

      Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
      if (authorOptional.isPresent()) {
        System.out.println(authorOptional.get().getName());
      }
    
    • 1
    • 2
    • 3
    • 4

    数据转换

    Optional还提供了map可以让我们对数据进行转换,并且转换得到的数据还是被Optional包装好的,保证了使用安全;

    如想的到作家的书籍集合:

            Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
    
            authorOptional.map(Author::getBooks)
                          .ifPresent(books -> books.forEach(System.out::println));
    ~~
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    msys如何编译64位ffmpeg 带x264 x265
    本地有依赖但是没有导入,提示程序包不存在
    【C++】入门(二):引用、内联、auto
    misc学习(3)
    awk命令应用
    Cookie与Session
    ORB-SLAM3算法学习—Frame构造
    你是怎么看待程序员不写注释这一事件的呢?
    创新案例|Amazon.com 2023 年营销策略:电子商务零售巨头商业案例研究
    JS鼠标、键盘、window、表单的事件类型
  • 原文地址:https://blog.csdn.net/cjl_xupt/article/details/126943384