来源:网络
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍; 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/; 截止目前,累计输出 73w+ 字,讲解图 3088+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2500+小伙伴加入
空指针异常是出现频率比较高的bug,在出现空指针时,很多小伙伴都是习惯性地加一个 !=null 的判断,这个bug就解决了。
当代码中频繁出现 !=null 的判断时,我们就会很头疼,能不能高效、优雅地做这个判断?
答案当然是可以的。
第一步 ,当我们要做 !=null 的判断时,请停顿一下,看一下我们要做判断的这个数据是什么类型?
数据类型无非就是String字符串、Object/自定义对象、List集合、Array数组、Map集合等类型。
第二步 ,思考这个数据类型对应的工具类有哪些?
String类型,对应的工具类有StringUtils。
Object对象,对应的工具类有ObjectUtils。
Array数组,对应的工具类有Arrays。
List集合、Map集合对应的工具类有Collections、CollectionUtils等。
这些工具类都是Java、Spring框架自带的工具类。
第三步 ,使用对应类型的工具类做判断。
1、如果这个数据是String类型时,请使用StringUtils工具类。
String str = "";
StringUtils.isEmpty(str); // true
StringUtils工具类比较有针对性,是针对String字符串的工具类。
public static boolean isEmpty(@Nullable Object str) {
return str == null || "".equals(str);
}
在isEmpty方法中,既有为null的判断,也有是否等于空字符串的判断。
2、如果这个数据是Object类型,请使用ObjectUtils工具类。
Object obj = null;
ObjectUtils.isEmpty(obj); // true
3、如果这个数据是Map类型,也可以使用ObjectUtils工具类。
Map<String,Object> map = Collections.emptyMap();
ObjectUtils.isEmpty(map);// true
4、如果这个数据是List类型,还可以使用ObjectUtils工具类。
List<Integer> list =Collections.EMPTY_LIST;
ObjectUtils.isEmpty(list); // true
5、如果这个数据是数组类型,依旧可以使用ObjectUtils工具类。
// 数组
Object[] objArr = null;
ObjectUtils.isEmpty(objArr); // true
ObjectUtils 中的isEmpty()这一个方法,分别可以对字符串、数组、Map集合、List集合进行是否等于null的判断。
这个isEmpty方法为什么能判断这么多种数据类型呢?一起看下它的源码。
public static boolean isEmpty(@Nullable Object obj) {
// 判断obj是否为null,如果是直接f
if (obj == null) {
return true;
}
// 判断obj是否是Optional的子类
if (obj instanceof Optional) {
// 如果是,则调用isPresent方法判断是否为null
return !((Optional) obj).isPresent();
}
// 判断obj是否是CharSequence的子类
if (obj instanceof CharSequence) {
// 如果是,则获取长度,长度等于0时,就认为这个obj是空字符串
return ((CharSequence) obj).length() == 0;
}
// 判断obj是否为数组
if (obj.getClass().isArray()) {
// 数组的长度等于0就认为这个数组是空数组
return Array.getLength(obj) == 0;
}
// 判断obj是否为Collection集合的子类
if (obj instanceof Collection) {
// 用Collection子类的isEmpty方法判断集合是否为空
return ((Collection) obj).isEmpty();
}
// 判断obj是否为Map接口的子类
if (obj instanceof Map) {
// 如果是,则进行强转,并用子类的isEmpty方法判断集合是否为空
return ((Map) obj).isEmpty();
}
// else
return false;
}
在这个静态方法中,首先对传入的obj对象进行是否等于null的判断,如果是则返回。如果不是null,对obj进行数据类型进行定位,然后根据数据类型进行判断。
在这个方法中,封装了Optional、CharSequence、Array、Collection、Map数据类型,几乎涵盖所有的数据类型。
通过这段源码,我们也可以看出,它对复杂类型的集合的判断存在一些缺陷。也就是说它只判断了集合的长度,集合的长度为0,就认为集合是空的。
// 创建一个只有一个元素的List集合
List<Integer> list = Collections.singletonList(null);
ObjectUtils.isEmpty(list); // false
上面的这段代码,我们创建了一个只有一个元素、且这个元素为null的List集合。
如果是对象数组,数组里有一个对象,但这一个对象为null,这个判断就失灵了。
ObjectUtils 类中对对象数组的判断是另外一个isEmpty方法。
public static boolean isEmpty(@Nullable Object[] array) {
return array == null || array.length == 0;
}
因此在这2种情况下,我们再使用ObjectUtils的isEmpty方法就不合适了,我们需要对集合或数组里的每一个元素进行判断是否为null。
6、针对List集合中元素是否为空的正确判断
Arrays.stream(list.toArray()).allMatch(ObjectUtils::isEmptyisNull);
这里用到了Arrays工具类。需要先把List集合转换成数组,然后再使用Arrays工具类对数组里的元素逐一判断是否为null。
7、针对Map集合是否为空为null的判断
Map<String,Object> map = Collections.emptyMap();
CollectionUtils.isEmpty(map);
CollectionUtils工具类中isEmpty判断方法源码:
public static boolean isEmpty(@Nullable Map<?, ?> map) {
return map == null || map.isEmpty();
}
map是否等于null,map集合是否为空,这一个方法中聚合了两个判断。我们直接调用它就可以减少我们的工作量。
除此之外,CollectionUtils工具类中还有针对List集合的isEmpty方法:
List<Integer> list = null;
// 使用CollectionUtils工具类判断list集合是否为空
CollectionUtils.isEmpty(list); // true
针对List集合的isEmpty源码:
public static boolean isEmpty(@Nullable Collection<?> collection) {
return collection == null || collection.isEmpty();
}
在这个方法中,既有为null的判断,也有isEmpty的判断,聚合了两个判断,我们直接调用它也可以减少我们的工作量。
最后总结一下
判断一个数据是否为null,可以经过三步,第一步思考属于什么数据类型,第二步根据数据类型选择正确的工具类,第三步,使用正确的工具类进行判断。
针对String字符串类型的数据,直接使用StringUtils工具类。
针对除了String之外的数据类型都可以使用ObjectUtils工具类。
针对List集合、Map集合,除了ObjectUtils还可以使用CollectionUtils工具类进行判断。
针对数组和List集合中的子元素是否都为null的判断,则需要遍历判断。
以上便是本次的总结,希望对你有帮助。
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍; 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/; 截止目前,累计输出 73w+ 字,讲解图 3088+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2500+小伙伴加入
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持小哈呀,谢谢啦