理解 Object 类在 Java 类体系中的核心地位
掌握 Object 类提供的关键方法及其用途
能够正确重写 toString()、equals()、hashCode() 等方法
了解对象克隆(clone())与垃圾回收(finalize())机制
初步认识线程通信相关方法(wait() / notify())
java.lang.Object 是 Java 所有类的根类。无论你是否显式继承,每一个 Java 类都直接或间接地继承自 Object。这意味着所有对象都天然具备 Object 提供的一组通用行为。
为什么需要 Object 类?
作为所有类的共同祖先,提供统一接口
定义所有对象共有的基础操作(如字符串表示、相等性判断)
支持哈希结构(如 HashMap、HashSet)的底层机制
提供线程间通信的基本能力(wait()、notify())
实现对象复制(clone())和资源清理(finalize())
toString()对象的字符串表示
默认返回格式:类名@十六进制哈希码(如 Person@13f79d8)。建议重写以提供更有意义的输出。
class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{name='" + name + "'}";
}
public static void main(String[] args) {
Person p = new Person("小明");
System.out.println(p.toString()); // 输出:Person{name='小明'}
System.out.println(p.hashCode()); // 输出:例如 123456789
}
}提示:
System.out.println(obj)会自动调用obj.toString()。
hashCode()对象的哈希值
返回一个 int 值,用于哈希表(如 HashMap)快速定位对象
重要规则:如果两个对象通过 equals() 判定为相等,则它们的 hashCode() 必须相同
class Employee {
int id = 101;
@Override
public int hashCode() {
return id * 31; // 常见做法:使用质数(如 31)参与计算
}
public static void main(String[] args) {
Employee e = new Employee();
System.out.println(e.hashCode()); // 输出:3131
}
}注意:
hashCode()不是内存地址!尽管默认实现可能与地址有关,但语义上它只是一个用于哈希的整数。
equals(Object obj)对象相等性判断
默认行为:比较引用是否相同(即 ==)
通常需要重写以实现基于内容的比较
class Book {
String title;
Book(String title) {
this.title = title;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Book other = (Book) obj;
return this.title.equals(other.title);
}
public static void main(String[] args) {
Book b1 = new Book("Java 编程思想");
Book b2 = new Book("Java 编程思想");
System.out.println(b1.equals(b2)); // 输出:true
}
}最佳实践:重写
equals()时,必须同时重写hashCode(),以保证哈希集合的正确性。
getClass()获取运行时类信息
返回当前对象的实际类型(Class 对象),常用于反射。
public class Main {
public static void main(String[] args) {
Object o = new String("Hello");
Class<?> clazz = o.getClass();
System.out.println("对象 o 的实际类型是: " + clazz.getName());
// 输出:java.lang.String
}
}finalize()对象销毁前的清理(已过时)
在垃圾回收器回收对象前调用
不推荐使用:从 Java 9 开始标记为 @Deprecated,Java 18+ 已移除
替代方案:使用 try-with-resources 或 Cleaner 类
警告:不要依赖
finalize()执行关键清理逻辑!
clone()对象克隆
创建并返回当前对象的副本
类必须实现 Cloneable 接口,否则抛出 CloneNotSupportedException
默认是浅拷贝(shallow copy)
class Student implements Cloneable {
int id = 1;
String name = "张三";
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); // 调用 Object 的 clone()
}
public static void main(String[] args) throws Exception {
Student s1 = new Student();
Student s2 = (Student) s1.clone();
System.out.println(s1.name); // 张三
System.out.println(s2.name); // 张三
}
}浅拷贝 vs 深拷贝:
浅拷贝:仅复制对象本身,内部引用仍指向原对象
深拷贝:递归复制所有嵌套对象(需手动实现)
wait()、notify()、notifyAll()
用于线程间协作,必须在 同步代码块(synchronized) 中调用。
这些方法属于高级并发编程内容,后续在多线程专题中深入讲解。
完整重写 Object 方法
class Book implements Cloneable {
private String title;
private String author;
private int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
@Override
public String toString() {
return title + " by " + author + " (" + year + ")";
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Book other = (Book) obj;
return year == other.year &&
title.equals(other.title) &&
author.equals(other.author);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + title.hashCode();
result = 31 * result + author.hashCode();
result = 31 * result + year;
return result;
}
@Override
public Book clone() {
try {
return (Book) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError("Clone 不应失败"); // 因为实现了 Cloneable
}
}
// getter 省略...
public static void main(String[] args) {
Book b1 = new Book("深入理解计算机系统", "Randal Bryant", 2010);
Book b2 = b1.clone();
System.out.println(b1); // 深入理解计算机系统 by Randal Bryant (2010)
System.out.println(b2); // 同上
System.out.println("b1 equals b2: " + b1.equals(b2)); // true
System.out.println("b1 hash: " + b1.hashCode());
System.out.println("b2 hash: " + b2.hashCode()); // 相同
b1 = null;
System.gc(); // 可能触发 finalize(不保证)
}
}黄金法则:只要重写了
equals(),就必须重写hashCode()!
为什么 Object 类中的 clone() 方法是 protected 的?这对接口设计有何影响?
如果两个对象 a.equals(b) 返回 true,但 a.hashCode() != b.hashCode(),会发生什么问题?
在现代 Java 开发中,有哪些方式可以替代 finalize() 来管理资源?