objects.equals能避免空指针异常,因其内部先判空:两者均null返回true,仅一者null返回false,仅当均非null时才调用a.equals(b)。

Objects.equals 为什么能避免空指针异常
Objects.equals 内部做了 null 安全判断:它先检查两个参数是否都为 null(此时返回 true),再检查其中一个为 null(此时返回 false),最后才调用第一个非 null 对象的 equals 方法。这避免了手动写 a != null && a.equals(b) 时因 a 为 null 而抛出 NullPointerException。
什么时候必须用 Objects.equals 而不是直接调用 equals
当你无法完全确定至少一个对象非 null 时,就该用 Objects.equals。典型场景包括:
- 从 Map.get()、List.get()、数据库查询结果中拿到的引用类型字段(如
User user = map.get("user")) - JSON 反序列化后未做校验的字段(如 Jackson 返回的
String name可能为null) - 方法参数未加
@NonNull注解或未做显式判空时 - 比较两个可能为
null的包装类变量(如Integer a, Integer b)
Objects.equals 和 ==、Objects.deepEquals 的关键区别
Objects.equals(a, b) 是语义相等判断,依赖对象自身的 equals 实现;== 比较的是引用是否相同;Objects.deepEquals 则递归处理数组和嵌套集合——但多数日常比较不需要它,且开销更大。
常见误用:
- 对基本类型(
int,boolean)误用Objects.equals:编译器会自动装箱,但有额外开销,应直接用== - 拿
Objects.equals比较两个数组(如int[]):它只比较引用,不会逐元素比,要用Arrays.equals(a, b) - 在
equals方法体内又调用Objects.equals(this.field, other.field)却没重写field类型的equals:仍可能 NPE,比如field是自定义类但没实现equals
一个容易被忽略的性能与兼容性细节
Objects.equals 在 Java 7 引入,Android API Level 19+ 支持;低于此版本需用 android.util.Objects.equals 或自行封装。另外,它虽轻量,但在高频循环(如每秒万级比较)中仍比直接 == 多两次判空分支——如果业务逻辑已确保非空,硬套 Objects.equals 反而多余。
真正要盯住的,是那些看起来“应该不为空”但实际可能为 null 的边界字段,比如 HTTP 请求里可选的 query 参数、配置中心动态下发的字符串开关。这些地方漏掉 Objects.equals,线上就容易冒出莫名其妙的 NullPointerException。










