代码优雅之道——Java如何判空

简介: java中一些判空的处理,中高级绕道

1、前言

实际项目中我们会有很多地方需要判空校验,如果不做判空校验则可能产生NullPointerException异常。

针对异常的处理我们在上一篇有提及:代码优雅之道——断言+Springboot统一异常处理

先来看一下实际项目中一些判空方式

通常我们判断一个对象是否为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对象的创建

publicfinalclassOptional<T> {
privatestaticfinalOptional<?>EMPTY=newOptional<>();
privatefinalTvalue;
//可以看到两个构造方格都是private 私有的//说明 没办法在外面new出来Optional对象privateOptional() {
this.value=null;
    }
privateOptional(Tvalue) {
this.value=Objects.requireNonNull(value);
    }
//这个静态方法大致 是创建出一个包装值为空的一个对象因为没有任何参数赋值publicstatic<T>Optional<T>empty() {
@SuppressWarnings("unchecked")
Optional<T>t= (Optional<T>) EMPTY;
returnt;
    }
//这个静态方法大致 是创建出一个包装值非空的一个对象 因为做了赋值publicstatic<T>Optional<T>of(Tvalue) {
returnnewOptional<>(value);
    }
//这个静态方法大致是 如果参数value为空,则创建空对象,如果不为空,则创建有参对象publicstatic<T>Optional<T>ofNullable(Tvalue) {
returnvalue==null?empty() : of(value);
    }
}

4.2使用场景

场景1:在service层中 查询一个对象,返回之后判断是否为空并做处理

场景2:使用Optional 和函数式编程,一行搞定

5、总结

每种方法的存在必然有适用的场景,有些情况下这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

相关文章
|
1天前
|
存储 缓存 监控
如何优化你的Java代码性能
如何优化你的Java代码性能
|
1天前
|
Java
Java自定义注解:优雅的代码标记
Java自定义注解:优雅的代码标记
9 1
|
1天前
|
存储 安全 Java
探索JAVA泛型:让代码在编译时就拥有金钟罩铁布衫!
【6月更文挑战第28天】Java泛型,自1.5版起,是代码安全性的守护者。它允许在类、接口和方法中使用类型参数,减少重复代码,提升可读性。泛型在编译时执行类型检查,防止运行时类型错误,如同给代码穿上“金钟罩铁布衫”。以Box类为例,泛型避免了显式转换,确保类型安全,让编程更加高效和无忧。
|
1天前
|
存储 前端开发 Java
Java 代码执行的原理解读
Java 代码执行的原理解读
|
1天前
|
设计模式 Java 开发者
Java中的代码优雅重构实战
Java中的代码优雅重构实战
|
1天前
|
存储 安全 Java
那些年,JAVA 泛型如何守护我们的代码梦?
【6月更文挑战第28天】Java 泛型,编程旅途的守护者,提升代码安全与效率。从繁琐的类型转换中解放,如列表示例所示,泛型简化了元素操作。自定义泛型类增强复用性,确保数据结构一致性,避免潜在错误。泛型,如同严谨的卫士,保障系统稳定,伴随开发者成长,铸就优雅、高效的代码世界。
|
1天前
|
存储 安全 Java
JAVA泛型大揭秘:如何在编译时守护你的代码安全?
【6月更文挑战第28天】Java泛型是JDK 5引入的特性,用于提升代码复用和类型安全性。通过类型参数如`&lt;T&gt;`,泛型在编译时确保数据类型的正确性。例如,泛型类`GenericList&lt;T&gt;`允许创建特定类型的列表,如`GenericList&lt;String&gt;`,阻止了不兼容类型元素的添加,防止运行时ClassCastException。泛型方法如`swap()`也确保了操作的类型安全,增强了代码的可读性和维护性。
|
1月前
|
Java
使用Java代码打印log日志
使用Java代码打印log日志
270 1
|
Java BI API
在Java代码中打日志需要注意什么?
日志是什么?日志是你在代码运行时打印出来的一些数据和记录,是快速排查问题的好帮手,是撕逼和甩锅的利器!
375 0
|
缓存 Java 网络架构
别在 Java 代码里乱打日志了,这才是正确的打日志姿势!
别在 Java 代码里乱打日志了,这才是正确的打日志姿势!
140 0