【优雅代码】03-optional杜绝空指针异常

【优雅代码】03-optional杜绝空指针异常

欢迎关注b站账号/公众号【六边形战士夏宁】,一个要把各项指标拉满的男人。该文章已在github目录收录。
屏幕前的大帅比大漂亮如果有帮助到你的话请顺手点个赞、加个收藏这对我真的很重要。别下次一定了,都不关注上哪下次一定。

1.背景介绍

在日常开发中总会遇到NPE问题,但是java提供了optional,可以让我们流畅写代码的同时避免NPE

2.建立Child、Parent、GrandParent的层级

建立如下结构的类GrandParent->Parent->List

  • Child
@Data @AllArgsConstructor @ToString(callSuper = true) @NoArgsConstructor @Accessors(chain = true) public class Child {     private List<String> list;     private String str; } 
  • GrandParent
@Data @AllArgsConstructor @ToString(callSuper = true) @NoArgsConstructor @Accessors(chain = true) public class GrandParent {     private Parent parent; } 
  • Parent
@Data @AllArgsConstructor @ToString(callSuper = true) @NoArgsConstructor @Accessors(chain = true) public class Parent {     private Child child; }  
  • 测试类
GrandParent opt1 = null; // 获取最底层数据。此时最顶层是null,不会报NPE String opt1Str = Optional.ofNullable(opt1).map(o1 -> o1.getParent())                 .map(o2 -> o2.getChild()).map(l -> l.getStr()).orElse(null); System.out.println(String.format("%s:%s", "opt1Object", opt1Str));  // 获取最底层数据。此时第二层是null,不会报NPE GrandParent opt2 = null; List<String> opt2list = Optional.ofNullable(opt2).map(o1 -> o1.getParent())                 .map(o2 -> o2.getChild()).map(l -> l.getList()).orElse(null); System.out.println(String.format("%s:%s", "opt2list", opt2list));  // 获取最底层数据。此时所有数据都是全的,无论是list还是string都没有问题 GrandParent opt3 = new GrandParent().setParent(new Parent().setChild(new Child().setStr("ssss").setList(Stream.of("1", "2").collect(Collectors.toList())))); List<String> opt3list = Optional.ofNullable(opt3).map(o1 -> o1.getParent())                 .map(o2 -> o2.getChild()).map(l -> l.getList()).orElse(null); String opt3Str = Optional.ofNullable(opt3).map(o1 -> o1.getParent())                 .map(o2 -> o2.getChild()).map(l -> l.getStr()).orElse(null); System.out.println(String.format("%s:%s", "opt3list", opt3list)); System.out.println(String.format("%s:%s", "opt3Str", opt3Str)); 
  • 输出结果
opt1Object:null opt2list:null opt3list:[1, 2] opt3Str:ssss 

可以发现嵌套类无论是string还是list,中间任何一个类为null都会直接返回null,而不用去多层嵌套if这种很蠢的做法

3.非常规复杂optional用法

当然平常时候总会遇到一些奇奇怪怪的结果,例如查询数据库会返回List<Map<String, String>>这样的结构,也是可以用Optinoal做的

// 获取list嵌map并随机返回一个key,此时list为null的获取不会NPE List<Map<String, String>> listR = null; String result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())         .flatMap(l -> l.keySet().stream().findAny()).orElse(null); System.out.println(result);  // 获取list嵌map并随机返回一个key,此时list无元素的获取不会NPE listR = new ArrayList<Map<String, String>>(); result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())         .flatMap(l -> l.keySet().stream().findAny()).orElse(null); System.out.println(result);  // 获取list嵌map并随机返回一个key,此时有1个HashMap,但HashMap无元素的获取不会NPE listR = new ArrayList<Map<String, String>>() {{     add(new HashMap<String, String>()); }}; result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())         .flatMap(l -> l.keySet().stream().findAny()).orElse(null); System.out.println(result);  // 获取list嵌map并随机返回一个key,此时所有结构完全 listR = new ArrayList<Map<String, String>>() {{     add(new HashMap<String, String>() {{         put("C", "0");     }}); }}; result = Optional.ofNullable(listR).flatMap(l -> l.stream().findAny())         .flatMap(l -> l.keySet().stream().findAny()).orElse(null); System.out.println(result); 

输出结果如下:

null null null C 

4.其它优秀杜绝空指针异常的优秀方法

首先是lombok的@NonNull,这个可以作用于方法参数上,如果传入空则直接抛异常,并在日志精准打印出异常位置及情况,非常适合校验参数,增加代码简洁性。非空指针的校验方式可以看优雅和前端交互

当然刚才写的类还是返回了null,但是没关系,可以用以下工具类,在各种情况下都可以抛出自定义异常或直接return出去

 // 常规对象的判空不会NPE System.out.println(String.format("%s:%s", "StringUtils", StringUtils.isBlank(null))); System.out.println(String.format("%s:%s", "defaultIfNull", ObjectUtils.defaultIfNull(null, "defaultIfNull"))); List list = null; Map map = null; Set set = null; String[] arr = null; // 常规collection的判空不会NPE System.out.println(String.format("%s:%s", "list", CollectionUtils.isEmpty(list))); System.out.println(String.format("%s:%s", "map", CollectionUtils.isEmpty(map))); System.out.println(String.format("%s:%s", "set", CollectionUtils.isEmpty(set))); System.out.println(String.format("%s:%s", "arr", ArrayUtils.isEmpty(arr))); 

输出结果如下:

StringUtils:true defaultIfNull:defaultIfNull list:true map:true set:true arr:true 

推荐这些技术文章:

Lamada List 去重及其它操作示例

 

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

private static <T> Predicate...

四连问:API 接口应该如何设计?如何保证安全?如何签名?如何防重?

作者:巨人大哥 来源:http://39sd.cn/A08A6在实际的业务中,难免会...

Spring Boot + Redis 实现各种操作

一、Jedis,Redisson,Lettuce 三者的区别
共同点:都提供了基于 Redis 操作的 Java API,只是封装程度,具体实现稍有不同。
不同点:

1.1、Jedis

是 Redis 的 Java 实现的客户端。支持基本的数据类型如:String、Hash、List、Set、Sorted Set。
特点:使用阻塞的 I/O,方法调用同步,程序流需要等到 socket 处...

聊聊如何实现一个带幂等模板的Kafka消费者

前言
不知道大家有没有这样的体验,你跟你团队的成员,宣导一些开发时注意事项,比如在使用消息队列时,在消费端处理消息时,需根据业务场景,考虑一下幂等。后面走查代码的时,会发现一些资浅的开发,在需要幂等判断的场景的情况下,仍然没做幂等判断。既然宣导无效,就干脆实现一个带幂等模板的消费者,然后开发基于这个模板进行消费端业务处理。本文就以spring-kafka举例,聊聊如何实现一个带幂等模板的kafk...

Java实现在线预览功能

java实现在线预览功能,需要用到  jacob.dll jacob.jar   预览pdf所需js  pdfobject.min.js
 
将上传文件转为pdf保存。  

    <div class="control-group">
<label class="control-l...

Java-MyBatis-Plus

MyBatis-Plus
一、框架结构

官网地址:https://baomidou.com/
二、入门案例
2.1 开发环境
IDE:idea 2019.2
JDK:JDK8+
构建工具:maven 3.5.4
MySQL版本:MySQL 5.7
Spring Boot:2.6.3
MyBatis-Plus:3.5.1
2.2 创建数据库及表
创建表
CREATE DATABASE `myba...

《回炉重造》——泛型

泛型
前言
以前学习到「泛型」的时候,只是浅浅的知道可以限制类型,并没有更深入理解,可以说基础的也没理解到位,只是浮于表面,所以,现在回炉重造,重学泛型!打好基础!

什么是泛型?
泛型(Generic),Generic 的意思有「一般化的,通用的」。

是 JDK 5 中引入的新特性,它提供编译时的类型安全检测,允许我们在编译时检测到非法的数据类型,本质是 参数化类型。

这里还涉及到一个词「...

LinkedList, Set 和 Map

1,LinkedList
1.1 LinkedList 介绍
底层数据存储结构为双向链表
链表头:
class LinkedList<E> {
Node<E> first;
Node<E> last;
int size();
}

Node 是 LinkedList 内部类!!!
节点 N...

Request和Response

1.1 POST和GET请求
1.1.1 GET请求
发出GET请求的主要方式:
(1)在浏览器输入URL按回车
(2)点击<a>超链接
(3)点击submit按钮,提交 <form method=“get”>表单
GET请求特点:
会将请求数据添加到请求URL地址的后面,只能提交少量的数据、不安全

1.1.2 POST请求
发出POST请求的方法如下:
点击...

黑马程序员-传智健康项目(第八章)

传智健康项目

黑马程序员-传智健康项目(第一章)
黑马程序员-传智健康项目(第二章)
黑马程序员-传智健康项目(第三章)
黑马程序员-传智健康项目(第四章)
黑马程序员-传智健康项目(第五章)
黑马程序员-传智健康项目(第六章)
黑马程序员-传智健康项目(第七章)
黑马程序员-传智健康项目(第八章)
黑马程序员-传智健康项目(第九章)
黑马程序员-传智健康项目(第十章)
黑马程序员-传智健康项...

文章标题:【优雅代码】03-optional杜绝空指针异常
文章链接:https://www.dianjilingqu.com/2079.html
本文章来源于网络,版权归原作者所有,如果本站文章侵犯了您的权益,请联系我们删除,联系邮箱:saisai#email.cn,感谢支持理解。
THE END
< <上一篇
下一篇>>