继承中保持equals与hashcode一致,须确保父类equals可靠(用getclass()而非instanceof),子类新增字段必须同步参与equals比较和hashcode计算,且调用super.equals(obj)时传原始obj而非转型引用。

继承场景下保持 equals 和 hashCode 一致,核心是避免“父类用 instanceof、子类调 super.equals()”这类看似省事实则危险的做法。关键不在要不要调父类方法,而在于父类的实现是否真正可靠。
先确认父类 equals 是否可信任
如果父类没重写 equals,或用了 instanceof 判类型(比如 obj instanceof Parent),那它天然允许子类实例通过检查——这会破坏对称性:子类 A 的 equals(B) 返回 true,但 B.equals(A) 却可能返回 false(因为 B 是子类,instanceof A 不成立)。
- 遇到这种情况,子类不能靠
super.equals(obj)修复,必须整体重写equals - 更稳妥的做法是推动父类改用
getClass() == obj.getClass(),或明确声明“不支持子类扩展” - 若父类已用
getClass()且逻辑正确,子类才可安全调用super.equals(obj)
子类新增字段时,equals 和 hashCode 必须同步扩展
子类加了新字段(比如 department),且该字段参与相等性判断,那它必须同时出现在 equals 比较和 hashCode 计算中。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
equals中:先调super.equals(obj),再检查this.department和that.department是否相等(用Objects.equals处理 null) -
hashCode中:不能只调super.hashCode()后简单叠加;必须重新用全部字段(含父类字段 + 新增字段)计算,例如Objects.hash(super.hashCode(), department)或更清晰的Objects.hash(name, age, department) - 漏掉新增字段 → 相等对象哈希值不同 → 在
HashSet中被当成两个对象
别让 getClass() 和转型顺序搞砸一致性
子类 equals 方法里,类型检查后要强制转型,但传给 super.equals() 的必须是原始 obj,不是转型后的引用。
- 错误写法:
return super.equals((Parent) obj);—— 父类内部若调getClass(),会拿到Parent.class,而非实际运行时类型,导致检查失败 - 正确写法:
return super.equals(obj) && Objects.equals(department, that.department); - 所有参与
equals比较的字段,一个都不能少地放进Objects.hash(...)
用 Lombok 省心但得懂它的默认行为
@EqualsAndHashCode 默认只基于非静态、非瞬态(non-transient)字段生成,且使用 getClass() 做类型检查,符合安全继承原则。
- 若需包含父类字段,加
callSuper = true;否则它只处理当前类字段,可能遗漏继承来的关键属性 - 若子类新增字段要参与比较,确保没被
exclude或标记为transient - 生成的
hashCode自动覆盖所有参与equals的字段,无需额外干预
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










