Java 处理 Null 值的简便方法

94 阅读2分钟

在编写 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 ...;
}

通过这样的方法,可以让代码更清晰,更容易维护。