1. 前言
在实际项目中,我们经常需要对各种变量或对象进行判空校验。这是因为,如果不进行判空校验,当遇到空值时,可能会导致程序出现NullPointerException异常。这是一种常见的运行时异常,它会在试图访问或操作空对象引用时发生。为了避免这种异常的出现,我们需要在使用变量或对象之前,进行仔细的判空校验,以确保它们的值是有效的,或者它们不是空值。通过进行判空校验,我们可以更好地保证程序的稳定性和可靠性,避免潜在的错误和异常。
2. 如何判断为null
2.1 常用判断
判断一个对象是否为null有多种方式。除了你提到的java.util中的Objects.nonNull(obj)和hutool中的ObjectUtil,还有其他一些常见的方法。以下是这些方法的详细描述:
- java.util.Objects.nonNull(obj)
这是Java标准库提供的一种方法,它检查给定的对象是否为null。如果对象不为null,则返回true;否则返回false。 - hutool中的ObjectUtil
Hutool是一个Java工具包,提供了许多实用的工具方法。ObjectUtil类中也有一个判断对象是否为null的方法。使用Hutool的ObjectUtil,你可以像这样检查一个对象是否为null:ObjectUtil.isNotNull(obj)
- null != obj
这是一种传统的比较方式,直接使用"!="运算符来检查一个对象是否为null。如果obj不为null,则表达式的结果为false;如果obj为null,则表达式的结果为true。
2.2 List的判空
像List这种比较特殊的在项目中可能不仅仅是判断非空了。对于List来说不等于null和List.size()
不等于0是两回事,公司也有实习生常常有把这两个混淆的情况,list不等于null说明已经初始化了,堆内存中有一块属于它的地盘,而size为0说明还没往里面放东西,举个例子说就是不等于null代表我现在有个瓶子,size大于0说明我向瓶子里装水了。
来看一下源码:
public boolean isEmpty(List list) { if (list != null && list.size() > 0) { return false; } else { return true; } }
相当于判断瓶子里有没有水(前提是瓶子已经存在,若瓶子不存在,则会抛出NullPointerException
异常)。
所以通常情况下会连用list != null && list.size > 0
来判断,或者直接使用HuTool中CollUtil工具的isEmpty。诸如此类的还有Set、Map等。
2.3 String的判空
这里还是用瓶子与水的概念,String为null时调用equals(String) 或 length() 等操作抛出 java.lang.NullPointerException。
private void test() { String str1 = null; //这里将抛出异常 if (str1.equals("")) { } //这里将抛出异常 if (str1.length() > 0) { } }
针对字符串判空有以下几种方式:
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
2.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 类似,要求返回值必须是OptionalT get()
: 获取容器中的元素,若容器为空则抛出NoSuchElement
异常
先看个常见的示例:
baseInfo类中有布尔类型的属性,是空返回false,不为空取其值,需要四行。
boolean blind = false; if (null != baseInfo.getBlind()) { blind = baseInfo.getBlind(); }
当使用Optional时,一行搞定,非常的优雅。
boolean blind = Optional.ofNullable(baseInfo.getBlind()).orElse(false);
Java中的Optional 是一个可以为null的容器对象。如果值存在则isPresent()方法返回true。调用get()方法会返回该对象。
创建Optional对象的方式有三种:
- 创建一个空的Optional对象:Optional.empty()。
- 使用非null值创建Optional对象:Optional.of(T value)。
- 使用任意值创建Optional对象:Optional.ofNullable(T value)。
Optional对象的使用场景主要是处理空指针异常的情况,相当于一个容器,当往里面存放对象时,如果对象为空(null),Optional会返回一个空的Optional实例,反之会返回一个非空的Optional实例。
以下是使用Optional对象的示例:
Optional<String> optional = Optional.ofNullable("test"); optional.isPresent(); // true optional.get(); // "test" optional.orElse("fallback"); // "test" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "t"
以上代码中,首先创建了一个包含字符串"test"的Optional对象。然后使用isPresent()方法检查该值是否为null,使用get()方法获取该值。接下来使用ifPresent()方法检查值是否存在,如果存在则执行lambda表达式中的代码。在这个例子中,输出结果是"t"。
总结来说,Java中的Optional对象可以用于避免空指针异常的情况,它提供了一种更优雅、更简洁的方式来处理可能为空的值。
3. 总结
每种方法都有其适用的场景,链式编程也不例外。虽然它可以使代码更优雅,但可能会降低逻辑性和可读性。因此,在项目中使用时,需要根据具体情况慎重考虑。