Java中统一处理输入参数空指针的核心是设计约束+工具辅助+规范落地:用Optional显式表达可选性,DTO+校验注解前置拦截,Objects.requireNonNull等断言提前失败,配合IDE和编译期检查减少漏判。

Java 中统一处理输入参数空指针,核心不是靠封装“消灭” null,而是通过设计约束 + 工具辅助 + 规范落地,在业务代码中提前拦截、明确语义、减少判空散落。
用 Optional 显式表达可选性
对真正可能为空且业务逻辑需要区分“有值/无值”的参数,用 Optional<T> 代替裸 T 类型。它强制调用方思考空值路径,避免隐式 null。
- Controller 层接收参数时,不直接写
User user,而是封装为Optional<User> userOpt(需配合自定义参数解析器或 DTO 包装) - Service 方法签名优先使用
Optional<Order> getOrderById(Long id),而非返回Order或抛异常,让调用方用ifPresent或orElse显式处理 - 注意:不要把 Optional 用作字段类型或返回集合——它不是容器,也不适合序列化
DTO + Lombok + 非空校验注解统一拦截
所有外部输入(HTTP 请求、MQ 消息)必须先经 DTO 接收,并用 JSR-303 注解声明约束,配合全局异常处理器统一拦截非法参数。
- DTO 中用
@NotBlank、@NotNull、@Valid(嵌套校验)标注必填字段 - Lombok 的
@Data+@Builder减少样板代码,配合@NonNull在构造/Setter 中触发 NPE(仅限内部构建,不替代校验) - Spring Boot 全局配置
@RestControllerAdvice捕获MethodArgumentNotValidException,返回标准化错误码和提示,如 “用户名不能为空”
工具类 + 静态断言提前失败
在 Service 或 Domain 层关键入口,用 Guava 或 Apache Commons 的工具方法做快速防御性检查,失败即抛明确业务异常,不传 null 进深层逻辑。
立即学习“Java免费学习笔记(深入)”;
- 用
Objects.requireNonNull(obj, "用户对象不可为空")替代if (obj == null) throw ... - 封装常用校验:如
Check.notBlank(name, "姓名")、Check.notNull(id, "订单ID"),复用且语义清晰 - 避免在每个 if 分支里重复写
if (xxx != null)—— 把“非空”作为前置契约,而不是分支逻辑
IDE 和编译期辅助减少漏判
借助开发环境提前发现潜在 null 引用,比运行时排查更高效。
- 启用 IntelliJ 的 Nullable/NotNull 注解检查(@Nullable/@NotNull),配合 Lombok 的
@RequiredArgsConstructor自动注入非空字段 - Maven 加入 Checker Framework 插件,在编译期做流敏感空值分析(适合高可靠性系统)
- Code Review 时重点关注:参数未校验就直接调用
.toString()、.getXXX()、.stream()的地方


















