文章目录
Java常用的判空方法
== :是一个比较运算符
==:既可以判断基本类型,又可以判断引用类型
==:如果判断的是基本类型,判断的是值是否相等。示例: int i=10; double d=10.0;
==:如果判断的是引用类型,判断的是地址是否相等,即判定是不是同一个对象
JDK 自带的判空方法
1. 使用 == 或 != 运算符
- 对于引用类型,可以使用
==
或!=
运算符来判断是否为null
Object obj;
if (obj == null) {
// 对象为空的处理逻辑
} else {
// 对象不为空的处理逻辑
}
2. 使用 equals 方法
- equals: 是Object类中的方法,只能判断引用类型。
- Object 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。
String str = "123";
if ("123".equals(str)) {
// 字符串不为空且等于"123"的处理逻辑
} else {
// 不相等或为 null
}
3. Objects.isNull / Objects.nonNull
String s = null;
if (Objects.isNull(s)) {
System.out.println("s 是 null");
}
if (Objects.nonNull(s)) {
System.out.println("s 不是 null");
}
4. Objects.equals
- 既能安全地判断两者是否相等,也能避免 NPE:
String a = null, b = "xdr";
if (Objects.equals(a, b)) {
System.out.println("a 与 b 相等");
} else {
System.out.println("a 与 b 不相等或其中之一为 null");
}
4. JDK8 中的 Optional
Optional<String> opt = Optional.ofNullable(getValue());
// 判空或提供默认值
String result = opt.orElse("default");
// 仅当存在时才执行
opt.ifPresent(v -> System.out.println("Value: " + v));
// 转换并取值
int len = opt.map(String::length).orElse(0);
第三方工具包
1. Apache Commons Lang3
(1)StringUtils
import org.apache.commons.lang3.StringUtils;
String str = " ";
boolean isEmpty = StringUtils.isEmpty(str); // true if null or length == 0
boolean isBlank = StringUtils.isBlank(str); // true if null, empty, or whitespace only
(2)ObjectUtils
import org.apache.commons.lang3.ObjectUtils;
Integer x = null;
// 如果 x 为 null,就返回默认值 100
int value = ObjectUtils.defaultIfNull(x, 100);
(3)Validate.notNull
import org.apache.commons.lang3.Validate;
public void process(@Nullable String param) {
// 如果 param 为 null,会抛出 NullPointerException
Validate.notNull(param, "param 不可为 null");
// 之后可以安全使用 param
}
2. Google Guava
import com.google.common.base.Strings;
import com.google.common.base.MoreObjects;
String s = null;
// 判空或空串
boolean isNullOrEmpty = Strings.isNullOrEmpty(s);
// 取第一个非 null 的值
String first = MoreObjects.firstNonNull(s, "fallback");
3. Lombok 注解
import lombok.NonNull;
public void save(@NonNull String name) {
// 如果传入 name 为 null,Lombok 会在编译时生成一个 null 校验并抛出 NPE
System.out.println("Saving " + name);
}
4. Vavr(函数式风格)
import io.vavr.control.Option;
Option<String> opt = Option.of(null);
opt.peek(v -> System.out.println("value: " + v))
.onEmpty(() -> System.out.println("No value"));
小节
- 以下是常见判空方式的适用场景、可读性与大致性能对比
方法 | 场景/用途 | 优点 | 缺点 | 性能(大致) |
---|---|---|---|---|
obj == null / obj != null |
最基础的引用类型判空 | 最直观、最轻量,CPU 层面就是一次单纯的指针比较 | 代码稍显啰嗦,不能直接判断空串或空白 | 最快 |
Objects.isNull(obj) nonNull() |
同上,但风格更统一 | 可读性稍好,链式流式 API (filter(Objects::nonNull) ) |
底层还是调用 obj == null ,无额外性能提升 |
与 == 相当 |
Objects.equals(a, b) |
安全的双侧相等比较(可能有一侧为 null ) |
一步搞定对称比较,无 NPE | 只做相等判断,不能区分 “一侧为 null” 还是 “都不等” | 微弱开销(静态方法调用) |
"const".equals(str) |
字符串常量内容比较防 NPE | NPE 保险,简洁 | 只能比较某个常量,与 null 判空是混用场景 |
极快,几乎和 == 相当 |
Optional.ofNullable(...).orElse(...) |
需要“取值或默认” 或做串联式空值处理 | 流式可读、链式转换、函数式风格 | 重对象分配、方法链调用、垃圾更频繁,不适合热路径或循环中频繁调用 | 最慢,不建议在性能敏感处 |
StringUtils.isBlank/isEmpty(...) |
判空串(null 、"" 、空白) |
语义清晰,一次判断多种“空”场景 | 需引入依赖(Apache Commons Lang) | 依赖少量方法调用 |
MoreObjects.firstNonNull(a, b) |
在 Guava 项目中取“首个非空” | 语义明确,单行搞定 | 同上需依赖 Guava;抛 NPE(若两者皆为 null) | 依赖少量方法调用 |
@NonNull (Lombok) |
方法入参校验 | 编译时自动生成 NPE 校验,消除手写 文档化注解 | 仅针对入参,编译时插桩;运行时抛 NullPointerException |
与手写 if (x==null) throw 相当 |
Option.of(...) (Vavr) |
纯函数式或复杂流式场景 | 函数式安全链式操作 | 学习成本、依赖较大;性能、GC 开销都比 Optional 略高 |
慢于 Optional |
综合建议
1、简单判空
性能最优:直接 obj == null / obj != null,尤其在高频调用、热点代码路径中。
流式场景:若要更好地融入 Java 8 流式 API,可用 Objects.nonNull 做过滤:
list.stream()
.filter(Objects::nonNull)
.forEach(...);
2、字符串判空/判空白
- 使用 StringUtils.isBlank(str)(Apache Commons Lang3)或 Strings.isNullOrEmpty(str)(Guava),比手写 str == null || str.trim().isEmpty() 更简洁。
3、安全比较
- 相等判断首选 Objects.equals(a, b),或把常量放前 “const”.equals(str),避免 NPE。
4、取默认值
- 如果只是“当 null 时返回默认值”,可优先 ObjectUtils.defaultIfNull(obj, defaultVal)(Lang3)或 MoreObjects.firstNonNull(obj, defaultVal)(Guava),比 Optional.ofNullable(obj).orElse(defaultVal) 轻量。
5、函数式风格
- 若项目已全面采用函数式(Vavr)或需要在 API 边界使用 Optional,可接受它们带来的对象分配和链式调用成本。但不建议在循环、热点方法里反复 new Optional。
6、注解校验
- 对于公共 API 的入参校验,推荐使用 Lombok 的 @NonNull(或用 @Validated/Bean Validation),把校验编译或运行时自动化,提升代码可读性和一致性。
性能排序(参考)
== / !=
Objects.isNull / nonNull
Objects.equals / "const".equals()
StringUtils.isBlank / Strings.isNullOrEmpty
ObjectUtils.defaultIfNull / MoreObjects.firstNonNull
Optional.ofNullable().orElse()
Vavr Option.of()
- 总体来说,最轻量的始终是最原生的 == null,在性能敏感、调用频繁的场景不必过度追求“风格统一”而牺牲性能;最推荐的日常写法则是根据类型(普通对象、字符串、取默认值)选最简洁、安全的工具方法。