java中equals处理null的核心原则是绝不主动调用可能为null对象的equals方法;推荐使用objects.equals()安全比较,它自动处理双null、单null及非null情况;自定义类重写equals时须首行判空,并用objects.equals比较字段;字符串比较禁用str.equals("value"),应选"value".equals(str)或objects.equals(str,"value")。

Java 中 equals 方法处理 null 值的核心原则是:**永远不主动调用可能为 null 的对象的 equals() 方法**。直接写 a.equals(b) 一旦 a 为 null 就会抛出 NullPointerException,这是最常见也最易忽略的风险点。
优先使用 Objects.equals() 替代手动判空
Java 7 起提供的 Objects.equals(a, b) 是最推荐、最简洁的安全方案。它内部已封装完整逻辑:
- 若
a和b都为null,返回true - 若仅其中一者为
null,返回false - 若两者均非
null,才调用a.equals(b)
等价于手动写的健壮判断:(a == b) || (a != null && a.equals(b)),但更少出错、更易读。适用于 String、Integer、自定义 POJO 字段等所有引用类型比较。
重写自定义类的 equals() 时必须检查参数是否为 null
在 @Override public boolean equals(Object obj) 中,第一步就应拦截 null 参数:
- 先用
if (obj == null) return false;快速拒绝 - 再用
if (getClass() != obj.getClass()) return false;或if (!(obj instanceof YourClass)) return false;确保类型一致 - 字段比较时,对可能为 null 的引用字段(如
String name),应使用Objects.equals(this.name, other.name),而不是this.name.equals(other.name)
这样既满足“非空性”契约(x.equals(null) 必须返回 false),也避免了在方法体内触发 NPE。
避免危险写法:字符串比较的常见陷阱
字符串比较尤其容易翻车。以下写法都不可取:
-
str.equals("value")—— 若str为null,立刻崩溃 -
str == "value"—— 比的是引用,语义错误
安全替代方案只有两种:
-
"value".equals(str)—— 利用字面量非 null 特性,适合单侧已知非空场景 -
Objects.equals(str, "value")—— 更通用、更清晰,两侧均可为 null
注意 Objects.equals 的边界与局限
它解决的是“调用安全”,不是“语义万能”:
- 对数组(如
String[])默认做引用比较,Objects.equals(new String[]{"a"}, new String[]{"a"})返回false;需改用Arrays.equals()或Objects.deepEquals() - 若你重写的
equals()方法本身没处理 null 或逻辑有误,Objects.equals()仍会走入错误逻辑——它只是安全地把锅交还给你 - 业务上是否认为两个
null相等,需结合上下文判断(例如数据库中NULL = NULL不成立)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











