Java函数式编程&Optional介绍、总结-java8新特性(三)

目录

一、Optional的介绍   

二、Optional的创建

1、Optional.ofNullable():推荐

2、Optional.of():不推荐

3、ofNullable()方法和of() 方法的区别:

4、ofNullable()和of() 等价的写法:

5、对Optional对象做进一步封装、提高代码复用性:

三、Optional安全获取值

1、get()方法:

2、orElseGet方法:

3、orElseThrow方法:

 四、Optional安全消费值

ifPresent()方法 推荐:

五、判断Optional内部是否存在数据

        isPresent():

六、Optional中的过滤方法filter()

七、Optional中的数据类型转换和计算map


一、Optional的介绍   

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

Author author = getAuthor();
if(author!=null){
     System.out.println(author.getName());
}

        尤其是对象中的属性还是一个对象的情况下,这种判断会更多,而过多的判断语句会让我们的代码显得臃肿不堪。

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

     基本原理: 实际上optional相当于是一个包装类,它把数据封装成了optional对象当中的value属性,我们可以直接去调用optional相关的一些方法帮我们进行相应的非空判断、操作封装进去的数据,这样就可以非常优雅的避免空指针异常了。

       接下来我们围绕着如何进行Optional对象的创建,以及如何安全的消费数据展开描述。

二、Optional的创建

1、Optional.ofNullable():推荐

        我们一般使用Optional的静态方法ofNullable()方法来把数据封装成一个Optional对象。无论传入的参数是否为null都不会出现问题,把要封装的数据直接传入到参数当中就可以了,它就能得到对应的optional对象,它的泛型就是你传入的数据的类型:

Author author = new Author();
Optional<Author> authorOptional = Optional.ofNullable(author);
2、Optional.of():不推荐

        如果你确定一个对象不是空的则可以使用Optional静态方法of()来把数据封装成Optional对象,但是如果传入进of()方法的对象为空,也会报空指针异常:

Author author = new Author();
Optional<Author> authorOptional = Optional.of(author);

3、ofNullable()方法和of() 方法的区别:

                         

        可以看到,我们传入数据value之后,它会对ofNullable()方法内部会对这个数据进行是否为空的判断:  如果为空,它会调用empty()方法,Optional.empty()方法会把null封装成optional对象返回, 也就是获取到一个option的对象; 但是如果它不为空,它会调用of方法来封装数据:

                                

           

4、ofNullable()和of() 等价的写法:
 private static void test13(){
        Optional<Author> authorOptional1 =getAuthorOptional1();
        Optional<Author> authorOptional2 =getAuthorOptional2();
    }

    private static Optional<Author> getAuthorOptional1(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(author);
    }

    private static Optional<Author> getAuthorOptional2(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return author == null ? Optional.empty():Optional.of(author);
    }
5、对Optional对象做进一步封装、提高代码复用性:
  Author author = getAuthor();
  optional<Author> authorOptional = optional.ofNullable(author);

  private static Author getAuthor(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return author ;
    //我们应该养成封装的习惯,返回Optional<Author>对象
  }

        你可能会觉得还要加一行代码来封装数据比较麻烦: 

        optional<Author>  authorOptional = optional.ofNullable(author);

        但是如果改造下getAuthor方法,让其返回值就是封装好的Optional的话,我们在使用时就会方便很多,推荐:

  private static Optional<Author> getAuthorOptional1(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(author);
        //直接返回一个Opptional<Author>对象,而不是Author对象
    }

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

三、Optional安全获取值

                get()方法        orElseGet()方法        orElseThrow()方法:

1、get()方法:

        如果我们期望安全获取值,不推荐使用get()方法获取,因为当Optional内部的数据为空的时候会出现异常:


        

        而是用如下的两个方法:

2、orElseGet方法:

        也可以用来获取值,并且当Optional对象内部的数据值为null的时候,你可以去设置一个默认值,如果当内部的数据值为null,它就会返回这个默认值。 

        当为null的时候:

  private static void test13(){
        Optional<Author> authorOptional =getAuthorOptional();
        Author author = authorOptional.orElseGet(() -> new Author());
        //当为null时就会new出来的Author对象进行返回
        System.out.println(author);
    }

    private static Optional<Author> getAuthorOptional(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(null);
    }

         不为null的时候:

  private static void test13(){
        Optional<Author> authorOptional =getAuthorOptional();
        Author author = authorOptional.orElseGet(() -> new Author());
        //当为null时就会new出来的Author对象进行返回
        System.out.println(author);
    }

    private static Optional<Author> getAuthorOptional(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(author);
    }

3、orElseThrow方法:


        获取数据,如果数据不为空则获取数据,如果为空则根据传入的参数来创建异常抛出,当我们使用spring这些框架的时候,当你抛出异常之后,我们可以使用spring去进行异常的统一的捕获,做统一的异常处理。 

        它里面其实也是需要一个Supplier接口,但是你要注意这个不太一样的地方,它的泛型是Throwable,它的返回值类型要求是一个Throwable:

   private static void test14(){
        Optional<Author> authorOptional =getAuthorOptional();
        try {
            Author author = authorOptional.orElseThrow(new Supplier<Throwable>() {
                public Throwable get() {
                    return new RuntimeException("数据为null");
                }
            });
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    private static void test15(){
        Optional<Author> authorOptional =getAuthorOptional();
        try {
            Author author = authorOptional.orElseThrow(()-> new RuntimeException("数据为null"));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

 如果为null:

                

 四、Optional安全消费值

ifPresent()方法 推荐:

        我们获取到一个Optional对象后肯定需要对其中的数据进行使用。这时候我们可以使用ifPresent()方法对Optional对象中的数据进行消费,如果Optional对象内部封装的数据不为空,不为空时才会执行具体的消费代码, 当数据为null的时候,这里面的数据消费操作是不会被执行的,这样就优雅的避免了空指针异常:

private static Optional<Author> getAuthor(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(author);
    }

    private static void test16(){
        Optional<Author> author = getAuthor();
        author.ifPresent(new Consumer<Author>() {
            @Override
            public void accept(Author author) {
                System.out.println("作家姓名为:" + author.getName());
            }
        });
    }

    private static void test17(){
        Optional<Author> author = getAuthor();
        author.ifPresent(author1 -> System.out.println("作家姓名为:" + author1.getName()));
    }

五、判断Optional内部是否存在数据

        isPresent():

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

private static Optional<Author> getAuthor(){
        Author author = new Author(1L,"蒙多",23,"一个从菜刀中明悟哲理的祖安人",null);
        return Optional.ofNullable(author);
    }

    private static void test18(){
        Optional<Author> author = getAuthor();
        if(author.isPresent()){
            //如果Optional中没有数据,if判断为false的话,就不会执行if代码块了
            System.out.println("作家姓名为:" + author.get().getName());
        }
    }

六、Optional中的过滤方法filter()

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

        

 private static void test19() {
        Optional<Author> author = getAuthor();
         author.filter(author1 -> author1.getAge() < 18)
                 .ifPresent(author2 -> System.out.println("作家姓名为:" + author.get().getName()));
    }

七、Optional中的数据类型转换和计算map

        类似于filter,这个map和Stream流当中的map方法的作用也是类似的,我们可以对数据进行相应的计算或者进行类型的转换,并且最终类型转换完之后的数据也是被Optional对象所封装,保证了我们使用的安全。

        Optional中的数据类型发生了变化:

    private static void test21(){
        Optional<Author> author = getAuthor();
        Optional<List<Book>> optionalBooks = author.map(author1 -> author1.getBooks());
        optionalBooks.ifPresent(books -> System.out.println(books));
    }

  private static void test21(){
        Optional<Author> author = getAuthor();
        author.map(author1 -> author1.getAge()+1000)
                .ifPresent(age -> System.out.println(age + "============"));
    }

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值