空指针异常本质是用null当真实对象调用方法,编译器不检查运行时null值,jvm在执行invokevirtual等指令时发现引用为null即抛出nullpointerexception;objects.requirenonnull()适用于构造器、api入口等契约校验场景,不可用于循环体内或替代逻辑判空。

它不是“指针出错”,而是你拿了一个 null 去当真实对象用——JVM 直接拒绝执行,抛出 java.lang.NullPointerException。
为什么调用 str.length() 就崩,但编译不报错
Java 编译器只检查语法和类型,不追踪变量运行时是否为 null。str 是 String 类型,调用 length() 语法合法,但若 str == null,JVM 在运行时发现“没对象可调”,立刻中断并打印堆栈。这种异常属于 RuntimeException,无需声明,也拦不住编译。
- 常见现象:
Cannot invoke "String.length()" because "str" is null(Java 14+ 启用-XX:+ShowCodeDetailsInExceptionMessages后的精确提示) - 别指望编译器提醒你——它连
String s = getFromDb(); s.trim();中getFromDb()可能返回null都不会预警 - IDE 的静态分析(如 IntelliJ 的 inspections)能标出部分风险,但覆盖有限,不能替代逻辑判断
Objects.requireNonNull() 该在哪儿用、不该在哪儿滥用
它是把“隐式崩溃”变成“显式失败”的最轻量手段,但不是万能胶布。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 适合场景:构造函数参数校验、Setter 入参、API 方法入口——
Objects.requireNonNull(user, "user must not be null") - 不适合场景:循环体内、高频 getter、日志输出前——每次调用都有方法栈开销,且掩盖了设计问题
- 注意:
requireNonNull()不会把null变成有效对象,它只抛异常;别和 Lombok 的@NonNull混用,后者只生成构造器/Setter 中的检查,不覆盖你手写的逻辑 - 错误用法示例:
for (String s : list) { Objects.requireNonNull(s); s.toUpperCase(); }——不如一开始就过滤掉null或用Optional包装返回值
链式调用 user.getAddress().getCity().toUpperCase() 怎么安全写
这不是风格问题,是可靠性分水岭。一行写到底,崩了你根本不知道 user、getAddress() 还是 getCity() 先为 null。
- 最直接的办法:拆开 + 显式判空
if (user != null && user.getAddress() != null && user.getAddress().getCity() != null) { ... } - 更清晰的办法:用
Optional表达契约意图Optional.ofNullable(user)<br> .map(User::getAddress)<br> .map(Address::getCity)<br> .map(String::toUpperCase)<br> .orElse("UNKNOWN"); - 最容易被忽略的坑:
Optional不该用于字段或参数包装——它不是null的替代品,而是返回值语义的显式声明;把private Optional<string> name;</string>当成常态,反而让调用方更难处理
Spring 中 @Autowired 字段为 null 怎么排查
这不是普通 NPE,是容器没接管对象生命周期的典型信号。
- 先确认类是否被 Spring 扫描到:检查包路径是否在
@ComponentScan范围内,类上是否有@Service/@Component等注解 - 别在 new 出来的对象里用
@Autowired——比如new MyService().doSomething(),此时字段必为null,因为 Spring 没参与实例化 - 构造器注入优于字段注入:
public MyService(OtherService other) { this.other = other; },Spring 在构造时就校验依赖,启动失败比运行时 NPE 更早暴露问题 - 如果必须用字段注入,加
@PostConstruct检查:@PostConstruct void checkDependencies() { if (otherService == null) throw new IllegalStateException("otherService not injected"); }
真正麻烦的从来不是“怎么 catch”,而是“哪个变量在哪儿悄悄变成了 null”。堆栈顶那行代码只是结果,上游的数据流、初始化顺序、容器生命周期,才是根因藏身之处。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










