重写equals方法必须保证非空性,即x.equals(null)恒返回false:第一步开头用==检查obj==null并返回false;第二步再进行类型检查(getclass()或instanceof);第三步字段比较用objects.equals()处理可能为null的引用字段。

重写 equals 方法时,保证非空性,核心就是让 x.equals(null) 永远返回 false,不抛 NullPointerException。这不是可选项,而是必须满足的契约——Java 官方规范明确要求 equals 具备“非空性”(null-safety)。
第一步:显式检查参数是否为 null
这是最直接、最不可绕过的防线。只要传入的是 null,立刻返回 false,不继续执行后续逻辑。
- 写法统一、清晰:
if (obj == null) return false; - 放在方法开头,越早越好,避免后续转型或字段访问触发 NPE
- 注意:这里用
==判断,不是.equals()——后者在 null 上会直接崩溃
第二步:类型检查要兼顾 null 安全
类型判断本身不能引入新的 null 风险。两种常用方式中,getClass() != obj.getClass() 和 !(obj instanceof Xxx) 行为不同,但都需以 null 检查为前提。
- 若已通过
obj == null检查,则后续obj.getClass()不会 NPE -
instanceof对null返回false,所以它本身是 null-safe 的;但若跳过显式 null 检查而只依赖instanceof,虽不报错,却掩盖了设计意图——非空性应主动声明,而非靠操作符隐式兜底 - 推荐组合:先
== null,再getClass()(适合严格类型匹配),或先== null,再instanceof(适合支持继承的场景)
第三步:字段比较前做空值防护
非空性不仅指参数本身,也包括对象内部字段。如果类中存在可能为 null 的引用字段(如 String name),直接用 == 或 .equals() 比较会出问题。
- 对引用字段,用
Objects.equals(a, b)最稳妥:它内部自动处理任一参数为null的情况,语义等价于a == b || (a != null && a.equals(b)) - 避免手写
a == null ? b == null : a.equals(b),易错且冗长 - 基本类型字段(如
int、boolean)无需判空,直接用==
为什么不能依赖 try-catch 来处理 null?
有人试图用 try { ... } catch (NullPointerException e) { return false; } 应对,这完全错误。
- 违背契约:非空性是语义约定,不是异常恢复场景
- 性能差:异常创建开销大,且本可静态避免的问题不该靠运行时捕获
- 掩盖真正 bug:万一其他位置真发生了意外 NPE,会被这个 catch 吞掉,难以定位
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











