object类是java所有类的根父类,其核心方法需深入理解:hashcode()与equals()必须成对重写以保证逻辑相等语义;tostring()应重写便于调试;wait()/notify()需在synchronized中使用以实现线程协作;getclass()、clone()、finalize()则需谨慎使用。

Object 类是 Java 中所有类的直接或间接父类,它定义了每个对象都具备的基本行为和通用契约。 理解它的核心方法,不只是为了应付面试,更是读懂框架源码、写出健壮代码、正确实现集合操作和并发逻辑的基础。
hashCode() 与 equals():必须成对重写
这两个方法共同维护“逻辑相等”的语义。默认实现中,equals() 比较的是引用地址,hashCode() 返回的是内存地址映射值 —— 这意味着两个内容相同但不同实例的对象,既不相等,哈希值也不同。
一旦你重写了 equals()(比如根据 id 和 name 判断两个 User 是否相等),就必须重写 hashCode(),否则会破坏哈希集合(如 HashMap、HashSet)的正常行为:同一个逻辑对象可能被存入多个位置,或根本查不到。
- 重写原则:如果 a.equals(b) 为 true,则 a.hashCode() 必须等于 b.hashCode()
- 推荐做法:用 IDE 自动生成(如 IntelliJ 的 Alt+Insert → equals and hashCode),它会基于你选的字段生成一致、高效的实现
- 注意:hashCode 不必唯一,但应尽量减少冲突;不要在 hashCode 中使用可变字段(如普通 setter 修改的属性),否则对象放入 HashSet 后修改字段会导致无法取出
toString():调试与日志的“第一张脸”
默认返回 类名@十六进制哈希值(如 User@1b6d3586),对排查问题几乎无用。重写后能让打印、日志、断点调试时一眼看清对象状态。
- 简洁清晰即可,不必追求完美格式,例如:
"User{id=101, name='Alice', age=28}" - 避免在 toString() 中触发复杂计算、远程调用或锁操作——它可能在任意线程、任意时机被调用(如 JMX、日志框架、IDE 变量面板)
- 可借助
Objects.toStringHelper()(Guava)或 Lombok 的@ToString简化编写
wait()/notify()/notifyAll():线程协作的底层原语
这三个方法不是用来“让线程睡几秒”的,而是配合 synchronized 实现线程间**条件等待与唤醒**,属于 Java 内存模型中“监视器(monitor)”机制的核心。
- 必须在 synchronized 方法或同步块中调用,否则抛
IllegalMonitorStateException -
wait()会释放当前对象锁,并进入等待队列;notify()唤醒一个等待线程(不保证哪个),notifyAll()唤醒全部 - 经典场景:生产者-消费者模式中,缓冲区满时生产者 wait,空时消费者 wait;任一角色操作后 notifyAll 通知对方检查条件
- 重要提醒:wait 被唤醒后需重新检查条件(用 while 循环包裹,而非 if),防止虚假唤醒(spurious wakeup)
getClass()、clone() 与 finalize():谨慎使用的特殊方法
getClass() 返回运行时真实 Class 对象,不可重写,常用于类型判断、反射获取泛型信息;clone() 默认是浅拷贝,要支持克隆必须实现 Cloneable 接口并重写,且需注意深拷贝逻辑;finalize() 已在 Java 9 标记为 deprecated,Java 18 彻底移除——资源清理请改用 try-with-resources 或 Cleaner API。
- 除非明确需要运行时类型信息(如 JSON 序列化框架识别子类),否则少用 getClass() 做类型分发,优先考虑多态或 Visitor 模式
- clone() 易出错且语义模糊,现代开发更倾向使用构造器、静态工厂方法或复制构造器(copy constructor)替代
- finalize() 不可靠、不可预测、性能差,绝不要依赖它释放关键资源(如文件句柄、数据库连接)








