objects.equals能避免空指针异常,因其内部先判两个null→true、仅一个null→false、均非null才调用a.equals(b);适用于map.get、optional、dto字段、泛型变量、字符串比较等易空场景,且语义清晰安全。

Objects.equals 能避免空指针异常,是因为它内部做了三层判空:两个都为 null → 返回 true;只有一个为 null → 返回 false;两个都不为 null → 才调用 a.equals(b)。你不用自己写 a != null && a.equals(b),也无需担心谁先谁后、漏判或顺序颠倒。
什么时候必须用 Objects.equals
以下情况直接调用 obj1.equals(obj2) 极易崩溃:
- 从 Map.get(key)、Optional.orElse(null) 或数据库查询结果中拿到的对象可能为 null
- DTO 字段未赋值、JSON 反序列化时字段缺失,导致对象引用不确定是否初始化
- 泛型类型变量(如
T t)在编译期无法判断是否可空,静态检查工具常报 warning - 字符串比较时,变量可能为 null —— 写成
"done".equals(status)虽安全,但不如Objects.equals(status, "done")语义清晰、统一可读
和 ==、手动 equals 的本质区别
== 比的是引用地址,对 String、Integer、自定义对象几乎总是错的;手动调用 a.equals(b) 一旦 a 为 null 就抛 NPE;而 Objects.equals(a, b) 是语义相等的安全封装,不依赖调用方预判哪边非空。
特别注意:它不改变 equals 方法本身的行为——如果类没重写 equals,仍走 Object 默认的引用比较;如果重写了但逻辑有误(比如没处理 null 参数),Objects.equals 也只是“安全地执行了错误逻辑”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
数组和浮点数的两个典型坑
Objects.equals 对数组是浅比较:
-
Objects.equals(new int[]{1}, new int[]{1})→ false(引用不同) - 正确做法:用
Arrays.equals(arr1, arr2)或Objects.deepEquals(arr1, arr2)
对 Double/Float 包装类:
-
Objects.equals(Double.NaN, Double.NaN)→ true(符合预期) -
Objects.equals(0.0, -0.0)→ false(继承 Double.equals 行为,这点容易被忽略)
配合 Stream 和 Lambda 更实用
在函数式编程中,它天然适配可能返回 null 的 getter:
-
list.stream().filter(x -> Objects.equals(x.getCode(), "A01"))→ 安全 -
list.stream().filter(x -> x.getCode().equals("A01"))→ 一旦 getCode() 返回 null,立刻 NPE
同理适用于 Optional.map、Map.computeIfAbsent 等场景,只要涉及“不确定是否为空”的比较,Objects.equals 就是默认首选。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










