Java案例怎么修复空指针异常?

wen java案例 59

本文目录导读:

Java案例怎么修复空指针异常?

  1. 定位空指针来源(第一步)
  2. 修复方案(按优先级)
  3. 实际案例修复(附完整代码)
  4. 高级根治手段
  5. 根本预防(避免NPE)
  6. 最实用的快速修复流程
  7. 注意:不要过度修复

在Java中修复空指针异常(NullPointerException,简称NPE)通常需要结合防御性编程工具辅助代码审查,以下是系统性的修复方案和实战案例。


定位空指针来源(第一步)

常见触发场景

String str = null;
str.length();              // 直接调用方法
array[0] = null;           // 数组元素为null
Map.get(key).toString();   // 链式调用

调试技巧

  • 看堆栈第一行at com.example.MyClass.myMethod(MyClass.java:25)
  • 看行号:IDE中双击行号可跳转(如IntelliJ IDEA)

修复方案(按优先级)

✅ 方案一:主动检查(防御性检查)

// 错误代码
String name = user.getName();
System.out.println(name.toUpperCase());
// 修复后
if (name != null) {
    System.out.println(name.toUpperCase());
} else {
    System.out.println("Default Name");
}

✅ 方案二:使用 Objects.requireNonNull()(快速失败)

public void setName(String name) {
    // 如果传入null,立即抛出NPE并明确提示
    this.name = Objects.requireNonNull(name, "姓名不能为空");
}

✅ 方案三:Stream API 中的 Optional(函数式风格)

// 错误:直接.get()可能NPE
String result = map.get("key").toString();
// 修复后
String result = Optional.ofNullable(map.get("key"))
                        .map(Object::toString)
                        .orElse("默认值");

✅ 方案四:使用 String.valueOf() 替代 toString()

// 可能NPE:obj可能为null
String s = obj.toString();
// 安全写法:null也返回"null"字符串
String s = String.valueOf(obj);

实际案例修复(附完整代码)

案例:用户服务中处理空引用

public class UserService {
    // 原始问题代码
    public String getUserDisplayName(Long userId) {
        User user = userRepository.findById(userId); // 可能返回null
        return user.getName();  // 可能NPE
    }
    // 修复版本1:防御性检查
    public String getUserDisplayNameFixed(Long userId) {
        User user = userRepository.findById(userId);
        if (user == null) {
            return "Unknown User";
        }
        String name = user.getName();
        return (name != null) ? name : "No Name";
    }
    // 修复版本2:Optional链式调用
    public String getUserDisplayNameWithOptional(Long userId) {
        return Optional.ofNullable(userRepository.findById(userId))
                       .map(User::getName)
                       .orElse("Guest");
    }
}

高级根治手段

基于注解的编译期检查

@NonNull
public String getEmail(@NonNull User user) { // 参数不能为null
    return user.getEmail(); // 返回值不能为null
}
  • 配合 Lombok:@NonNull@Nullable
  • 配合 IDE 静态分析(IntelliJ:@NotNull

使用 Objects.toString()

// 替代 null 检查 + toString
String result = Objects.toString(obj, "Default");

根本预防(避免NPE)

手段 说明 示例
参数校验 方法入口检查 if (input == null) throw new IllegalArgumentException(...)
集合返回空容器 不返回null return list != null ? list : Collections.emptyList();
默认值初始化 成员变量赋初值 private String name = "";
使用生成器模式 避免部分构造 Lombok @Builder

最实用的快速修复流程

  1. 看堆栈第一行定位类和方法
  2. 在该行打断点,观察哪一个是 null
  3. 将可疑的调用加 if (xxx != null) 包裹
  4. 如果频繁出现,考虑用 Optional 重构

注意:不要过度修复

// 过度:多层嵌套if,代码难以阅读
if (a != null && a.getB() != null && a.getB().getC() != null) {
    ...
}

推荐替代

Optional.ofNullable(a)
        .map(A::getB)
        .map(B::getC)
        .ifPresent(c -> { ... });

场景 推荐修复方式
简单变量 if != null 检查
方法参数 Objects.requireNonNull()
链式调用 Optional.map().orElse()
集合操作 stream().filter(Objects::nonNull)
遗留代码 添加空检查并打印日志

快速口诀:先定位,后判断;能用Optional别裸调;参数进来先检查,返回值不要给null。

抱歉,评论功能暂时关闭!