多态下重写equals和hashcode的核心是保障等价契约:抽象类用getclass()校验类型、只比较自身字段;子类先调super.equals()再扩展自有字段;hashcode须与equals字段严格一致,用objects.hash确保安全。

多态下重写 equals 和 hashCode,核心是让父类引用调用时行为可预测、不破环等价契约——不是为了让不同子类实例互相相等,而是确保同一抽象层级的对象比较逻辑一致、对称、可复用。
抽象类的 equals 必须用 getClass() 做类型校验
抽象类本身不能被 new,但运行时常见 Shape s = new Circle() 这类多态引用。若用 instanceof 判断类型,会导致 Circle.equals(Shape) 为 true,而 Shape.equals(Circle) 为 false,直接破坏对称性。
正确做法是:
- 在抽象类
equals中使用getClass() == obj.getClass()严格校验运行时类型 - 只比较抽象类自身声明的字段(如
id、name),不访问子类特有属性或可能被重写的 getter 方法 - 判空、自反、类型一致后,用
Objects.equals(a, b)比较各字段,自动处理 null 安全
子类重写 equals 是扩展,不是覆盖
子类不应从头写一套 equals,而应在父类逻辑基础上叠加自有字段。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
典型结构:
- 先调用
super.equals(obj)确保父类部分相等 - 再将
obj强制转为当前子类类型(因父类已通过getClass()校验,转型安全) - 用
Objects.equals比较子类新增字段,包括集合、数组等复杂类型
hashCode 必须与 equals 字段完全同步
只要两个对象 equals 返回 true,它们的 hashCode 就必须相同。漏掉任一参与 equals 的字段,对象放入 HashSet 或作 HashMap 键时就会丢失或重复。
推荐写法:
- 抽象类
hashCode:仅基于自身参与equals的字段,例如return Objects.hash(id, name); - 子类
hashCode:组合父类哈希与自有字段,例如return Objects.hash(super.hashCode(), radius, color); - 避免在
hashCode中调用可能抛异常、懒加载或返回可变结果的方法
避开继承场景下的典型陷阱
实际开发中出问题,往往不是逻辑错,而是细节不统一:
- 父类用了
instanceof?那子类无法靠super.equals()修复——必须整体重写,并统一改为getClass() - 手动遍历集合比较?改用
Objects.equals(set1, set2),它已处理顺序无关、null 安全、元素递归比较 - 字段含浮点数?需用
Float.floatToIntBits()或Double.doubleToLongBits()转换后再参与哈希计算
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










