代码优雅之道——Java如何判空
胖虎和朋友原创的视频教程有兴趣的可以看看 :
(文末附课程大纲)
来源:juejin.cn/post/7224027867084292154
- 1 前言
- 2 List的判空
- 3 String的判空
- 4 Optional
- 4.1 Optional对象的创建
- 4.2 使用场景
- 5 总结
1 前言
实际项目中我们会有很多地方需要判空校验,如果不做判空校验则可能产生NullPointerException
异常。
针对异常的处理我们在上一篇有提及:
先来看一下实际项目中一些判空方式
图片
图片
通常我们判断一个对象是否为Null,可以使用java.util
中的Objects.nonNull(obj)
、hutool中的ObjectUtil或者直接 null != obj
2 List的判空
像List这种比较特殊的在项目中可能不仅仅是判断非空了。对于List来说不等于null和List.size()
不等于0是两回事,公司也有实习生常常有把这两个混淆的情况,list不等于null说明已经初始化了,堆内存中有一块属于它的地盘,而size为0说明还没往里面放东西,举个例子说就是不等于null代表我现在有个瓶子,size大于0说明我向瓶子里装水了。
实际项目中也发现有直接用list.isEmpty()
去判断的,来看一下源码:
图片
相当于判断瓶子里有没有水(前提是瓶子已经存在,若瓶子不存在,则会抛出NullPointerException
异常)。
所以通常情况下会连用list != null && list.size > 0
来判断,或者直接使用HuTool中CollUtil工具的isEmpty。诸如此类的还有Set、Map等
3 String的判空
这里还是用瓶子与水的概念,String为null时调用equals(String)
或 length()
等操作抛出 java.lang.NullPointerException
。
图片
针对字符串判空有以下几种方式:
1、大多数人使用的方法之一,直观,方便,但效率低下:
if(a == null || a.equals(""));
2、比较字符串长度,高效:
if(a == null || a.length() == 0);
3、Java SE 6.0 才刚刚开始提供,效率和方法二差不多:
if(a == null || a.isEmpty());
当然还可以使用org.apache.commons.lang.StringUtils
工具。
StringUtils.isNotBlank(a);
- StringUtils.isNotBlank(null) = false
- StringUtils.isNotBlank("") = false
- StringUtils.isNotBlank(" ") = false
- StringUtils.isNotBlank("bob") = true
- StringUtils.isNotBlank(" bob ") = true
该工具类中还有个isNotEmpty()
方法,从注释可以很明显看出二者的差别
StringUtils.isNotEmpty(a);
- StringUtils.isNotEmpty(null) = false
- StringUtils.isNotEmpty("") = false
- StringUtils.isNotEmpty(" ") = true
- StringUtils.isNotEmpty("bob") = true
- StringUtils.isNotEmpty(" bob ") = true
4 Optional
Optional的出现就是用来防止NullpointException
的。常见的方法有:
-
.empty()
: 创建一个空的Optional实例 -
.of(T t)
: 创建一个Optional 实例,为null时报异常 -
.ofNullable(T t)
: 若t 不为null,创建Optional 实例,否则创建空实例 -
isPresent()
: 判断容器中是否有值 -
ifPresent(Consume lambda)
: 容器若不为空则执行括号中的Lambda表达式 -
orElse(T t)
: 获取容器中的元素,若容器为空则返回括号中的默认值 -
orElseGet(Supplier s)
: 如果调用对象包含值,返回该值,否则返回s 获取的值 -
orElseThrow()
: 如果为空,就抛出定义的异常,如果不为空返回当前对象 -
map(Function f)
: 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
-
flatMap(Function mapper)
: 与map 类似,要求返回值必须是Optional -
T get()
: 获取容器中的元素,若容器为空则抛出NoSuchElement
异常
先看个常见的示例:
baseInfo类中有布尔类型的属性,是空返回false,不为空取其值,需要四行。
图片
当使用Optional时,一行搞定,非常的优雅。
图片
4.1 Optional对象的创建
public final class Optional<T> {
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
//可以看到两个构造方格都是private 私有的
//说明 没办法在外面new出来Optional对象
private Optional() {
this.value = null;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
//这个静态方法大致 是创建出一个包装值为空的一个对象因为没有任何参数赋值
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
//这个静态方法大致 是创建出一个包装值非空的一个对象 因为做了赋值
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
//这个静态方法大致是 如果参数value为空,则创建空对象,如果不为空,则创建有参对象
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
}
4.2 使用场景
场景1:在service层中 查询一个对象,返回之后判断是否为空并做处理
图片
场景2:使用Optional 和函数式编程,一行搞定
图片
5 总结
每种方法的存在必然有适用的场景,有些情况下这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。
胖虎联合两位大佬朋友,一位是知名培训机构讲师和科大讯飞架构,联合打造了 《Java架构师成长之路》 的视频教程。完全对标外面2万左右的培训课程。
除了基本的视频教程之外,还提供了超详细的课堂笔记,以及源码等资料包..
课程阶段:
- Java核心 提升阅读源码的内功心法
- 深入讲解企业开发必备技术栈,夯实基础,为跳槽加薪增加筹码
- 分布式架构设计方法论。为学习分布式微服务做铺垫
- 学习NetFilx公司产品,如Eureka、Hystrix、Zuul、Feign、Ribbon等,以及学习Spring Cloud Alibabba体系
- 微服务架构下的性能优化
- 中间件源码剖析
- 元原生以及虚拟化技术
- 从0开始,项目实战 SpringCloud Alibaba电商项目
点击下方超链接查看详情 (或者点击文末阅读原文):
(点击查看) 2024年,最新Java架构师成长之路 视频教程!
以下是课程大纲,大家可以双击打开原图查看