1. 引言
本文将介绍四种检查对象所有变量是否为 null
的实现方法,每种方法都有其适用场景和注意事项。
2. 为何需要检查 null 变量
在 Java 中,null
表示变量未指向任何内存地址或未被初始化。关键点:
- 仅实例变量可为
null
,基本类型(如int
、double
)不能为null
- 未检查的
null
可能导致IllegalArgumentException
或NullPointerException
- 嵌套对象未初始化时,访问其成员会触发运行时错误
以以下 Car
类为例:
public class Car {
Integer power;
Integer year;
}
3. 使用 if 语句
最直接的方式是逐个检查字段。在 Car
类中添加方法:
public boolean allNull() {
if (power != null) return false;
if (year != null) return false;
return true;
}
测试验证:
@Test
public void givenNullFields_whenCheckForNullsUsingIfs_thenReturnCorrectValue(){
Car car = new Car();
assertTrue(car.allNull());
}
⚠️ 缺点: 每新增字段需添加 if
语句,维护成本高。仅适用于字段少且稳定的类。
4. 使用 Stream API
通过 Stream.allMatch()
实现声明式检查:
public boolean allNullV2() {
return Stream.of(power, year)
.allMatch(Objects::isNull);
}
测试验证:
@Test
public void givenNullFields_whenCheckForNullsUsingStreams_thenReturnCorrectValue(){
Car car = new Car();
assertTrue(car.allNullV2());
}
✅ 优点: 新增字段只需在 Stream.of()
中添加参数,比 if
语句更简洁。
5. 使用 Apache Commons 的 ObjectUtils
引入依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
直接使用 ObjectUtils.allNull()
:
@Test
public void givenNullFields_whenCheckForNullsUsingApacheCommons_thenReturnCorrectValue(){
Car car = new Car();
assertTrue(ObjectUtils.allNull(car.power, car.year));
}
⚠️ 权衡: 引入外部库解决简单问题需评估必要性,但 API 通用性强。
6. 使用反射 API
创建通用工具类 NullChecker
:
public class NullChecker {
public static boolean allNull(Object target) {
return Arrays.stream(target.getClass()
.getDeclaredFields())
.peek(f -> f.setAccessible(true))
.map(f -> getFieldValue(f, target))
.allMatch(Objects::isNull);
}
private static Object getFieldValue(Field field, Object target) {
try {
return field.get(target);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
测试验证:
@Test
public void givenNullFields_whenCheckForNullsUsingReflection_thenReturnCorrectValue() {
Car car = new Car();
assertTrue(NullChecker.allNull(car));
}
✅ 优势: 完全通用,新增字段无需修改检查逻辑
❌ 缺陷:
- 反射破坏封装性,编译期无法发现错误
- 性能开销较大(运行时处理更多逻辑)
7. 总结
方法 | 适用场景 | 维护成本 | 性能 |
---|---|---|---|
if 语句 | 字段极少且稳定的类 | 高 | 最佳 |
Stream API | 字段数量中等的普通类 | 中 | 良好 |
Apache Commons | 已引入该库的项目 | 低 | 良好 |
反射 API | 需要极致通用性的框架级代码 | 最低 | 较差 |
核心建议: 优先选择 Stream API 或 Apache Commons,反射 API 仅在必须通用化时谨慎使用。完整代码示例见 GitHub。