【优雅代码】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 ...
随机推荐
- Java事务与JTA
一.什么是JAVA事务 通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令.更简答的说就是:要么 ...
- Linux学习 - fdisk分区
一.fdisk命令分区过程 系统一旦重启,分区将消失 1 添加新硬盘 直接在虚拟机上添加 2 查看新硬盘 fdisk -l 3 分区 fdisk /dev/sdb fdisk进入/dev/sdb硬件设 ...
- canal安装与使用
安装 alpha的版本不是稳定的版本 wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deploye ...
- 【C/C++】链表/ListNode/数据结构
vector的操作 添加元素: 向尾部添加一个元素 vector<int> a; a.push_back(1); 向尾部添加多个元素 -向尾部添加x个同样的元素: a.insert(a.e ...
- Quartz在.NET中的使用
一.背景 例如需要在某年某月去将数据库的某个数据更新或者同步,又或者是每隔一段时间来执行一部分代码去调用接口,但是又不想人为的手动去执行 针对此类业务可以使用"定时调用任务",市面 ...
- MySQL如何使用coalesce函数
coalesce(a,b,c); 参数说明:如果a==null,则选择b:如果b==null,则选择c:如果a!=null,则选择a:如果a b c 都为null ,则返回为null(没意义)
- 降低制作门槛,人人都是3D“模”术师
12月14日,HDD(Huawei Developer Day)深圳站圆满举办.国内3D扫描类开发团队看书击水为大家分享了与HMS Core 3D建模服务的合作之旅,讲述了如何通过3D物体建模能力为其 ...
- 在【自定义列】中使用M函数(Power Query 之 M 语言)
数据源: "品名"一列 目标: 提取品名中的首字符,生成新列:"品名简称" 解决方案: 在[自定义列]中使用M函数Text.Start 步骤: 打开[自定义列] ...
- 别被调查汇总郁闷到——有Excel呢!
年初的某天,我在家待得好好的,好吧,其实也不是待得好好的,这事大家都知道,新冠病毒嘛,都锁家里了,还好本妖向来宅--呃--跑题了--肥来! 其实我能在家好好地待着,有水有电有Wi-Fi,那是有多少人冒 ...
- CF1520D Same Differences 题解
Content 给定 \(n\) 个数 \(a_1,a_2,\dots,a_n\),求有多少个二元组 \((i,j)\) 满足: \(i<j\). \(a_j-a_i=j-i\). 数据范围:\ ...