objects.equals() 能防 npe因其内部先判空再调用equals,支持双侧null;适用于可能为null的对象比较,不适用基本类型,性能好且比手写安全;注意数组、浮点数等特殊行为。

Objects.equals() 为什么能防 NPE
因为 Objects.equals() 内部做了 null 安全判断:它先检查两个参数是否都为 null,再检查是否引用相等,最后才调用 a.equals(b)。所以哪怕传入 null,也不会抛 NullPointerException。
常见错误现象是直接写 a.equals(b),结果 a 是 null 就崩了;而有人误以为 b.equals(a) 更安全——其实只要 b 是 null 同样挂。
- 适用场景:任意两个可能为
null的对象比较(尤其是字段、返回值、集合元素) - 不适用于基本类型:比如
int、boolean,得用Objects.equals(Integer.valueOf(a), Integer.valueOf(b))或直接用== - 性能影响极小:一次空检查 + 一次引用比较 + 一次方法调用,比手写三元表达式
(a == b) || (a != null && a.equals(b))更简洁且不易错
和 ==、String.equals() 的关键区别
== 比的是引用,String.equals() 是实例方法,调用前必须确保左边非 null;Objects.equals() 是静态工具方法,左右都可 null。
典型翻车现场:str1.equals(str2) 在 str1 为 null 时直接报 NullPointerException;而 Objects.equals(str1, str2) 安全返回 false。
立即学习“Java免费学习笔记(深入)”;
- 字符串比较优先用
Objects.equals(str1, str2),别再手写str1 != null && str1.equals(str2) -
Objects.equals()不会自动处理大小写,需要忽略大小写请显式转:Objects.equals(str1 != null ? str1.toLowerCase() : null, str2 != null ? str2.toLowerCase() : null),或改用String.equalsIgnoreCase() - 自定义类要让
Objects.equals()有意义,必须重写equals()和hashCode(),否则默认行为还是引用比较
在 Map.get() 和 Collections.contains() 中的正确用法
很多人以为 map.get(key) 里传 null key 就会 NPE——其实 HashMap 允许 null key,但某些集合(如 ConcurrentHashMap)不允许;而 Objects.equals() 本身不涉及集合操作,但它常被用来“安全地构造判断条件”。
真实易错点:写 list.contains(obj) 前没确认 obj 是否可能 null,而 ArrayList.contains() 内部调的是 Objects.equals(),所以其实是安全的;但你自己实现的 contains 方法若没套 Objects.equals(),就可能崩。
-
Map的get()不依赖Objects.equals(),它用的是key.hashCode()和key.equals(),所以 key 为null时,必须确保key.equals()能接住(比如HashMap对nullkey 有特殊处理) - 自己写工具方法判断是否存在某对象时,统一用
Objects.equals(candidate, target),而不是candidate.equals(target) - 注意:
Objects.equals()不会帮你解包Optional,Objects.equals(opt1, opt2)比较的是两个Optional实例,不是它们封装的值
容易被忽略的边界:数组、浮点数、BigDecimal
Objects.equals() 对数组直接用 == 比较引用,不会进内容比对;对 float/double 用的是 ==,但 NaN == NaN 返回 false,而 Objects.equals(Float.NaN, Float.NaN) 返回 true——这是它唯一“增强”语义的地方。
但这也意味着:如果你期望浮点数按误差范围比较(比如 Math.abs(a - b) ),<code>Objects.equals() 完全帮不上忙。
- 数组比较要用
Arrays.equals(arr1, arr2),不是Objects.equals(arr1, arr2) -
BigDecimal推荐用compareTo()判断相等(因0.0和0.00的equals()返回false),所以Objects.equals(bd1, bd2)可能不符合业务预期 - 泛型擦除后,
Objects.equals()接收的是Object,编译期不校验类型兼容性,运行时靠具体equals()实现兜底——这点和手写判空逻辑一样,没额外风险,但也别指望它做类型检查
最常漏掉的是数组和 BigDecimal 场景,一上来就套 Objects.equals(),结果逻辑跑偏还不报错。










