objects.equals()可安全比较可能为null的对象而不抛npe,它先判空再调用equals;直接调用obj.equals()或误写object.equals()会导致npe或编译错误。

为什么直接用 == 或 obj.equals() 会抛出 NullPointerException
当调用 obj.equals(other) 时,如果 obj 是 null,JVM 会立刻抛出 NullPointerException —— 因为方法调用语法要求接收者(receiver)必须是非空引用。而 == 虽能安全比较 null,但对非基本类型只比引用,无法满足逻辑相等判断需求。
Object.equals() 是怎么解决这个问题的
Objects.equals()(注意是 java.util.Objects 中的静态方法,不是 Object.equals())内部做了空值防护:它先检查两个参数是否都为 null,再检查是否引用相等,最后才调用 a.equals(b)。所以只要传入任意一个或两个 null,都不会 NPE。
常见误写是直接调用 Object.equals(a, b) —— 这个方法根本不存在;正确的是 Objects.equals(a, b)。
- ✅ 正确:
Objects.equals(str1, str2) - ❌ 错误:
Object.equals(str1, str2)(编译不通过) - ⚠️ 危险:
str1.equals(str2)(str1为null时崩溃)
什么时候该用 Objects.equals(),什么时候不该用
适用于需要语义相等(比如字符串内容、集合元素结构)、且任一操作数可能为 null 的场景。典型如 DTO 字段比对、Map 的 key 查找、数据库查询结果判空后比较。
不适合的场景:
- 性能敏感的循环内高频调用(
Objects.equals()多两次 null 检查,开销虽小但可避免) - 已明确非空(比如刚 new 出来的对象、@NonNull 参数、Optional.get() 后)—— 强行套用反而掩盖逻辑缺陷
- 自定义类未重写
equals(),又依赖默认引用比较时,Objects.equals()和==行为一致,但语义易误导
示例:
String name1 = getUser().getName(); // 可能 null
String name2 = request.getName(); // 可能 null
if (Objects.equals(name1, name2)) { // 安全
// ...
}
替代方案与边界情况提醒
除了 Objects.equals(),你也可以手写空值判断,但容易漏条件:
- ❌
a == b || a.equals(b):若a非空、b为null,仍 NPE - ✅
a == b || (a != null && a.equals(b)):等价于Objects.equals()的逻辑
注意:Objects.equals() 不处理递归深度比较(如嵌套对象),也不做类型转换("1" 和 1 永远不等)。如果字段是泛型容器(如 List<string></string>),确保其元素类型的 equals() 已正确定义。
最常被忽略的一点:它不改变 null 本身的含义 —— 如果业务上 null 和空字符串/默认值需视为不同,那用了 Objects.equals() 只是防了 NPE,没解决语义歧义。










