在编写 Java 代码时,null 常常是引发错误的“元凶”。为了让代码更稳定易维护,下面分享几种处理 null 值的实用技巧。
1. 返回 Optional 对象
Optional 相当于一个容器,里面可能有值,也可能是空的。用 Optional 可以减少直接返回 null 带来的问题,避免 NullPointerException(NPE)。
public Optional<SomeObject> getSomeObject() {
SomeObject object = ...; // 获取对象
if (object == null) {
return Optional.empty();
}
return Optional.of(object);
}
// 调用方代码
Optional<SomeObject> result = getSomeObject();
result.ifPresent(obj -> { // 使用 obj });
2. 返回自定义结果类
返回自定义结果类和 Optional 类似,但更加灵活。特别是需要详细错误信息时,Optional 可能不太够用。这种方式可以返回更多信息,提供更多控制,比如接口响应体封装类。
public class FunctionResult<T> {
private boolean success;
private String msg;
private T data;
// 创建成功结果
public static <T> FunctionResult<T> success(T data) {
FunctionResult<T> result = new FunctionResult<>();
result.success = true;
result.data = data;
return result;
}
// 创建失败结果
public static <T> FunctionResult<T> failure(String msg) {
FunctionResult<T> result = new FunctionResult<>();
result.success = false;
result.msg = msg;
return result;
}
public boolean isSuccess() {
return success;
}
public T getData() {
return data;
}
public String getMsg() {
return msg;
}
}
// 函数实现
public FunctionResult func() {
try {
SomeObject object = ...; // 获取对象
return FunctionResult.success(object);
} catch (Exception e) {
log.error("发生异常", e);
return FunctionResult.failure("错误信息");
}
}
// 调用方代码
FunctionResult result = func();
if (result.isSuccess()) {
SomeObject obj = result.getData(); // 使用 obj
} else {
// 处理错误
System.out.println(result.getMsg());
}
3. 返回空对象或默认值
有时返回一个空对象或者默认值,而不是 null,可以避免后续处理的麻烦。比如由于异常退出导致业务流程中断。
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
public class NullCircle extends Circle {
public NullCircle() {
super(0);
}
@Override
public double area() {
return 0;
}
}
Circle circle = ...; // 可能为 null
Circle safeCircle = (circle != null) ? circle : new NullCircle();
double area = safeCircle.area();
4. 抛出异常
如果发生异常,可以抛出自定义异常。这让调用方在 catch 块中处理异常,将错误处理和业务逻辑分开,代码更清晰。
// 自定义异常类
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
// 函数实现
public SomeObject func() throws CustomException {
SomeObject object = ...; // 获取对象
if (object == null) {
throw new CustomException("对象不存在");
}
return object;
}
// 调用方代码
try {
SomeObject obj = func();
// 使用 obj
} catch (CustomException e) {
// 处理异常
System.err.println(e.getMessage());
}
5. 简单处理 null 返回值的小技巧
如果觉得上面的方法麻烦了点,或者时间紧迫,可以试试下面的方法处理 null 值:
- 函数命名:给函数起一个明确的名字,例如把
myFunc改成myFuncNullable,这样调用这个函数的人就知道它可能会返回null。 - 注解:使用
@Nullable注解。很多现代的 IDE 可以识别这个注解,并在你使用函数返回值时给你提示,方便你发现可能的null问题。
// 可能会返回 null 的函数
public @Nullable String getNullableString() {
return ...;
}
// 函数命名
public String getUserNameNullable() {
return ...;
}
通过这样的方法,可以让代码更清晰,更容易维护。