当前位置 博文首页 > 文章内容

    JDK8中Optional类巧用之判空操作

    作者:shunshunshun18 栏目:未分类 时间:2021-08-29 14:43:31

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    前言

    相信大家肯定所有的开发者都对Java8里面的所有的东西都感兴趣,虽然目前的 JDK 已经更新到 JDK17 了,但是我相信,现在很多公司使用的还都是 JDK8 甚至是 JDK7,但是,就算是有些公司已经升级到 JDK8 但是对于 JDK8 里面的一些东西的使用,却没有使用的淋漓尽致。 今天就给大家放出几个 JDK8 里面比较好用的。

    JDK8

    大家都是知道 JDK8 就开始使用 Lambda 表达式,但是很多不管是在教程上还是在其他的书籍上,都没有说在实际开发的时候去使用上这个 Lambda 表达式,而且包括 JDK8 里面的一些新的类,也都没有引入,所以阿粉在这里想要给大家安利一波使用方面的知识。

    Optional类

    这个类对于大家来说,是一个非常重要的类,不知道大家有没有被 java.lang.NullPointerException 疯狂的折磨过,不管是新人开发还是老开发,遇到这个问题的时候,都是头大的很,因为我们要在代码里面去疯狂的判断是否是null,如果不是 null 需要怎么处理,如果是 null 需要怎么处理,反正就是你要是想解决 java.lang.NullPointerException 这个问题,就免不了去加一些判断条件,而 Optional 这个类,则是帮你优雅的处理 null 的问题。

    我们先看一组 Java7 中的一些判断空的实现:

     User user = usersMapper.selectUserById(userId);
     String userName = user.getUserName();
        if(user!= null){
            if(userName != null && !userName.isEmpty()){
                    .....
                  }
        }
    

    阿粉相信大家一定都写过这个样子的代码,因为我们不知道SQL查询出来的数据中是否包含了我们的 Users 对象,如果要是 Users 对象,那么就会无情的出现 java.lang.NullPointerException 这个空指针异常,这时候就很尴尬了,老开发一脸懵逼,我竟然还有的地方没有验证?

    但是验证了之后,你就会发现代码量是非常的大,而且有点不太美观,我们再来对比一下 JDK8 中,给我们提供的方法来进行验证的方式。

    User user = usersMapper.selectUserById(userId);
    Optional.ofNullable(user)
            .map(User::getUserName)
            .ifPresent(userName->{
            ....
            }
    

    大家看这种链式编程,ofNullable() 方法给我们提供了判断 user 是不是空,并且去校验 userName,如果存在,然后执行下面的逻辑,相比较 JDK7 的内容,相信大家看起来的话肯定是没有 JDK7 中的表现的那么的明显,但是大家看代码是不是发现已经被处理的妥妥的了。而且非常的优雅。

    相信大家肯定都看过一些教程,上面会写到:

        User user = usersMapper.selectUserById(userId);
        Optional<User> userOptional = Optional.ofNullable(user);
        Optional<String> str = userOptional.map(User::getUserName);
        ....
    

    但是相对于代码的可读性来说,我们肯定还是希望使用 JDK7 上面的判断来进行判断,但是这种 JDK8 的链式编程,在一定程度上减少了代码量,并且开发效率也会相对应的提升。

    如果大家不信,我们可以来运行一下我们的代码,然后看一下效果。

    Optional.ofNullable(user)
            .map(User::getUserName)
            .ifPresent(userName->{
                System.out.println("用户UserName不为空");
            });
    

    大家看,是不是就出现了我们想要的结果,一个判断 null 的操作,瞬间变得高大上了,而且代码的逼格瞬间上升一个档次。

    对于 Optional 类,在 Java8 实战中给出了很多的方法,阿粉也是给大家摘取了一下,做了个总结,

    • ofNullable 方法 :将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象
    • empty 方法 :返回一个空的Optional实例
    • filter 方法 :如果值存在并且满足提供的谓词,就返回包含该值的Optional对象;否则返回一个空的 Optional对象
    • flatMap 方法 :如果值存在,就对该值执行提供的mapping函数调用,返回一个Optional类型的值,否则就返 回一个空的Optional对象
    • get 方法 :如果该值存在,将该值用Optional封装返回,否则抛出一个NoSuchElementException异常
    • ifPresent 方法 :如果值存在,就执行使用该值的方法调用,否则什么也不做
    • isPresent 方法 :如果值存在就返回true,否则返回false
    • map 方法 :如果值存在,就对该值执行提供的mapping函数调用
    • of 方法 :将指定值用Optional封装之后返回,如果该值为null,则抛出一个NullPointerException异常
    • orElse 方法:如果有值则将其返回,否则返回一个默认值
    • orElseGet 方法 :如果有值则将其返回,否则返回一个由指定的Supplier接口生成的值
    • orElseThrow 方法 :如果有值则将其返回,否则抛出一个由指定的Supplier接口生成的异常

    大家看这些方法是不是都有很多相似的,比如 map,flatMap,还有orElse,orElseGet,orElseThrow 方法

    map 和 flatMap 比较:

    这两个都是做 转换值 的操作,区别就是入参的类型不是一样的,map的入参是 Function<? super T, ? extends U> mapper 而 flatMap 入参则是 Function<? super T, Optional<U> > mapper 。

    入参的不同也就导致了他们获取返回值也是不同的,map中获取的返回值自动被Optional包装,flatMap中返回值保持不变,但必须是Optional类型。

    这么一看总是感觉不太对的样子,我们去源码里面看看是什么样子的。

    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));
            }
        }
    
    
    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 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional。

    一个是比较聪明的,另外一个就相对来说不是那么聪明了,人家会自己包装呀,是不是?

    同样的比较还有 orElse,orElseGet,orElseThrow 但是这个阿粉就不再给大家絮叨了,因为上面的方法解释上都很明显的能看到了。

    Lambda 表达式

    Lambda 表达式实际上就是相当于是一个匿名内部类,他就是让我们开发的人把函数当成参数传递给某个方法,然后把代码当做数据去处理。

    阿粉相信大家肯定都了解这块,就比如说下面的代码对比:

    Java7:
    
        List<String> stringList = Arrays.asList("1", "2", "3");
            for (String st:stringList) {
                System.out.println(st);
            }
    
    Java8:
    
    Arrays.asList("1", "2", "3").forEach((String st)->{
                System.out.println(st);
            });
    

    同样的一个循环,我们肯定想用第二种写法不是么?

    va8:

    Arrays.asList("1", "2", "3").forEach((String st)->{
                System.out.println(st);
            });
    
    

    同样的一个循环,我们肯定想用第二种写法不是么?

    Java8 实际上在从发布开始,很多公司都在用,但是也有很多人依旧选择是 Java7,因为不想改变自己的学习风格,阿粉相信大家如果是一个决心在开发领域一直做下去的人,那么肯定会保持一个不断学习的心,所以,你是这样的人么?

    总结