Object类继承的哪些方法通常需重写?是否还有其他可选方法?
除equals()、hashCode()、toString()外,类中常用的方法及解析
1. compareTo()(需实现Comparable接口)
- 为什么用:让类的实例能按自然规则排序,直接适配
TreeSet、TreeMap这类有序集合,也能直接用Collections.sort()对实例列表排序。 - 工作逻辑:返回int值——正数代表当前对象比参数对象大,负数代表小,0代表相等。重写时必须和
equals()保持一致:如果a.compareTo(b) == 0,那a.equals(b)必须为true,不然有序集合会出现逻辑混乱。 - 场景示例:自定义
User类要按年龄排序,实现Comparable<User>后重写该方法,就能直接对List<User>排序,不用额外写比较器。
2. clone()(需实现Cloneable接口)
- 为什么用:快速创建对象副本,避免直接引用导致原对象被意外修改。
- 工作逻辑:默认是浅拷贝——只复制对象的引用,不会复制引用指向的内部对象。如果要深拷贝,得自己在重写时手动复制所有可变成员的内部状态。注意:
Cloneable是标记接口,不实现的话调用clone()会抛CloneNotSupportedException。 - 提醒:现在更推荐用拷贝构造函数或工厂方法做对象复制,因为
clone()的设计有缺陷,比如浅拷贝的隐式行为、异常处理麻烦。
3. 序列化相关:readObject()、writeObject()(需实现Serializable接口)
- 为什么用:自定义对象的序列化/反序列化逻辑,比如控制哪些字段被序列化、加密敏感数据、或者在反序列化后恢复对象的额外状态。
- 工作逻辑:序列化时JVM会自动调用
writeObject(),把对象状态写入输出流;反序列化时调用readObject(),从输入流恢复状态。如果不重写,JVM会默认序列化所有非transient字段。 - 场景示例:类里有密码字段,标记为
transient后,在writeObject()里加密再写入,readObject()里解密恢复,避免明文序列化。
4. finalize()(已废弃,仅作了解)
- 曾经的用途:作为对象被垃圾回收前的最后清理机会,比如释放文件句柄、数据库连接这类外部资源。
- 工作逻辑:由垃圾回收器自动调用,但执行时机完全不确定,甚至可能永远不执行。Java 9开始标记为废弃,现在推荐用
try-with-resources或者显式的资源关闭方法替代。
5. canEqual()(可选但实用)
- 为什么用:解决子类继承
equals()时的逻辑不对称问题——比如父类实例和子类实例判断相等时,可能出现父.equals(子)为true,但子.equals(父)为false的情况。 - 工作逻辑:在父类的
equals()里加判断if (!(obj instanceof MyClass) || !obj.canEqual(this)) return false;,子类重写canEqual()返回true,确保只有同类型(或兼容类型)的对象才会进行相等判断。
内容的提问来源于stack exchange,提问作者Detinoy
相关产品推荐
相关产品推荐

