【优雅代码】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
【优雅代码】03-optional杜绝空指针异常的更多相关文章
- 【优雅代码】04-1行代码完成多线程,别再写runnable了
[优雅代码]04-1行代码完成多线程,别再写runnable了 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮 ...
- 【优雅代码】01-lombok精选注解及原理
[优雅代码]01-lombok精选注解及原理 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...
- 【优雅代码】02-java传个方法你会吗,不是Method对象
[优雅代码]02-java传个方法你会吗,不是Method对象 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮 ...
- 【优雅代码】07-spring下的优秀工具类
[优雅代码]07-spring下的优秀工具类 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...
- Java开发笔记(七十七)使用Optional规避空指针异常
前面在介绍清单用法的时候,讲到了既能使用for循环遍历清单,也能通过stream流式加工清单.譬如从一个苹果清单中挑选出红苹果清单,采取for循环和流式处理都可以实现.下面是通过for循环挑出红苹果清 ...
- 【优雅代码】深入浅出 妙用Javascript中apply、call、bind
这篇文章实在是很难下笔,因为网上相关文章不胜枚举. 巧合的是前些天看到阮老师的一篇文章的一句话: “对我来说,博客首先是一种知识管理工具,其次才是传播工具.我的技术文章,主要用来整理我还不懂的知识.我 ...
- 超轻量级异步JS框架,别再让嵌套影响我们的优雅代码!
1.异步JS的重要性 随着Web平台地位的提升,霸占着浏览器的JavaScript语言也成为了世界上最流行的语言之一,甚至通过Node.js进入了服务器编程领域.JavaScript的一个重要特性便是 ...
- 编写优雅代码,从挖掉恶心的if/else 开始
背景 长话短说, 作为开发人员经常需要根据条件灵活查询数据库,不管你是用rawsql 还是EFCore, 以下类似伪代码大家都可能遇到: /// <summary> /// 灵活查询 能耗 ...
- 强迫症犯了,忍不住赞一下slf4j包Logger.java的优雅代码
如下是slf4j-api包下的Logger接口类里其中几个方法的声明: package org.slf4j; public interface Logger { /** * Log a message ...
随机推荐
- Oracle 学习PL/SQL
先上一张实用的图:用于转义字符的. SQL> select chr(42) ||'is what?' from dual; CHR(42)||---------*is what? 想转义哪个就转 ...
- Spring(4):Mybatis和Spring整合
第一步:创建数据库 MySQL代码 1 CREATE DATABASE `mybatis` ; 2 3 USE `mybatis`; 4 5 CREATE TABLE `user` ( 6 `id` ...
- 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入
参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...
- 如何优雅正确地通过interrupt方法中断线程
为什么废弃Thread的stop函数? 简单来说就是stop方法中断线程太过暴力随意,且会是否线程持有的锁,会导致线程安全问题.还有可能导致存在需要被释放的资源得不到释放,引发内存泄露.所以用stop ...
- gitlab官方api使用
目录 一.简介 二.技术要点 三.案例 一.简介 Gitlab作为一个开源.强大的分布式版本控制系统,已经成为互联网公司.软件开发公司的主流版本管理工具.使用过Gitlab的都知道,想要提交一段代码, ...
- hooks中,useState异步问题解决方案
问题描述: 在hooks中,修改状态的是通过useState返回的修改函数实现的.它的功能类似于class组件中的this.setState().而且,这两种方式都是异步的.可是this.setSta ...
- Sql 查询语句优化
sql查询很慢,很多时候并不是数据量大,而是sql语法使用不正确,本文讲述了基础语法使用,避免一些不必要的坑. explain select * from user;--查询执行时间 目录 Sql 优 ...
- YC-Framework版本更新:V1.0.3
分布式微服务框架:YC-Framework版本更新V1.0.3!!! 本次版本V1.0.3更新 集成分布式事务Seata: 集成分布式事务Tx-LCN: 集成Kafka: 集成RocketMQ: 集成 ...
- 延时间隔(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 像"饭前洗手"这种事,绝大部分情况下,是洗完手马上就可以动筷子开吃,但总会有意外,比如手都洗好了,突然 ...
- shell判断新字符串列表是否在老字符串列表中
for sn in `cat 12.30-new`;do if ! [[ `cat 12.30-old` =~ $sn ]];then echo $sn; fi; done