Java中所有类的根父类——Object
。
1. Object类概述
java.lang.Object
类是Java类层次结构中的根类。每个类都使用 Object
作为超类(父类)。所有对象(包括数组)都实现了这个类的方法。
这意味着,在Java中,你可以用 Object
类型的变量来引用任何类型的对象。这就是Java实现多态性的基石之一。
// 可以用Object引用指向任何对象
Object obj1 = new String("Hello");
Object obj2 = new Integer(100);
Object obj3 = new MyCustomClass();
Object obj4 = new int[]{1, 2, 3}; // 数组也是对象
2. 常用方法详解
Object类提供了多个核心方法,其中一些经常需要被子类重写以实现特定的逻辑。
2.1 toString()
- 作用:返回该对象的字符串表示。
- 默认实现:返回
类名@哈希码的无符号十六进制表示
(例如java.lang.Object@1b6d3586
)。 - 为什么要重写:默认的返回值对于调试和日志记录来说不直观。重写此方法可以返回一个能简洁地表达对象内容、易于阅读的字符串。
- 约定:建议为所有子类重写此方法,返回一个“简洁但信息丰富、易于阅读”的字符串。
// 未重写toString
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Person person = new Person("Alice", 25);
System.out.println(person); // 输出:com.example.Person@1b6d3586
}
}
// 重写toString后
public class Person {
private String name;
private int age;
// ... 构造方法等
@Override
public String toString() {
// 返回一个描述对象内容的字符串
return "Person{name='" + name + "', age=" + age + '}';
}
public static void main(String[] args) {
Person person = new Person("Alice", 25);
System.out.println(person); // 输出:Person{name='Alice', age=25}
// 当对象被用在字符串连接中时,也会自动调用其toString()方法
String info = "Person Info: " + person;
System.out.println(info); // 输出:Person Info: Person{name='Alice', age=25}
}
}
2.2 equals(Object obj)
- 作用:指示其他某个对象是否与此对象“相等”。
- 默认实现:比较两个对象的内存地址是否相同(即
==
的比较)。 - 为什么要重写:当我们希望根据对象的内容(即字段的值)来判断逻辑上的相等,而不是根据内存地址时,就需要重写此方法。
- 重写约定(必须遵循的规则):
- 自反性:
x.equals(x)
必须返回true
。 - 对称性:如果
x.equals(y)
为true
,那么y.equals(x)
也必须为true
。 - 传递性:如果
x.equals(y)
为true
,且y.equals(z)
为true
,那么x.equals(z)
也必须为true
。 - 一致性:只要对象内容没变,多次调用
x.equals(y)
应该始终返回相同的结果。 - 对于任何非
null
的引用值x
,x.equals(null)
必须返回false
。
- 自反性:
public class Person {
private String name;
private int age;
// ... 构造方法、toString等
@Override
public boolean equals(Object obj) {
// 1. 检查是否是同一个对象的引用
if (this == obj) return true;
// 2. 检查传入对象是否为null,或者是否是同一个类
if (obj == null || this.getClass() != obj.getClass()) return false;
// 3. 将obj向下转型为Person
Person person = (Person) obj;
// 4. 比较关键字段的值
// 使用Objects.equals来处理可能为null的name字段
return age == person.age && Objects.equals(name, person.name);
}
}
2.3 hashCode()
- 作用:返回对象的哈希码值。主要用于哈希表(如
HashMap
,HashSet
,Hashtable
)中。 - 与
equals()
的关系(非常重要):- 如果两个对象根据
equals()
方法是相等的,那么对这两个对象中的每个对象调用hashCode
方法都必须生成相同的整数结果。 - 如果两个对象根据
equals()
方法是不相等的,不要求它们的hashCode
值也必须不同。但是,为不相等的对象生成不同的哈希码可以提高哈希表的性能。
- 如果两个对象根据
- 为什么要重写:当你重写了
equals()
方法,就必须重写hashCode()
方法,以遵守上述约定。否则,你的对象在放入哈希集合时会出现不可预知的行为。
public class Person {
private String name;
private int age;
// ... 构造方法、toString、equals等
@Override
public int hashCode() {
// 使用Objects.hash()工具方法,可以方便地计算多个字段的哈希值
return Objects.hash(name, age);
}
}
2.4 getClass()
- 作用:返回此
Object
的运行时类(即实际类型)。 - 特点:这是一个
final
方法,不能被重写。它返回一个Class
对象,可以通过该对象获取类的元信息(如类名、方法、字段等),是Java反射机制的入口。
Person person = new Person("Bob", 30);
Class<?> clazz = person.getClass();
System.out.println(clazz.getName()); // 输出:com.example.Person
System.out.println(clazz.getSimpleName()); // 输出:Person
2.5 clone()
- 作用:创建并返回此对象的一个副本。
- 注意点:
- 要使用
clone()
,类必须实现Cloneable
标记接口,否则会抛出CloneNotSupportedException
。 - 默认的
clone()
方法是“浅拷贝”。如果对象包含引用类型的字段,拷贝对象和原对象将共享这些引用字段。如果需要“深拷贝”,必须在重写clone()
方法时手动处理。
- 要使用
public class Person implements Cloneable {
private String name;
private int age;
// ... 其他方法
@Override
public Object clone() throws CloneNotSupportedException {
// 先调用super.clone()进行浅拷贝
Person cloned = (Person) super.clone();
// 如果需要深拷贝,在这里对引用类型字段进行克隆
// cloned.someReference = (SomeClass) this.someReference.clone();
return cloned;
}
}
2.6 finalize()
- 作用:当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。用于在对象被回收前执行清理操作。
- 重要提示:此方法已过时(Deprecated),从Java 9开始标记为废弃。它的执行时机不确定,甚至不保证会被调用。依赖
finalize()
进行资源清理是非常危险的,容易导致内存泄漏和性能问题。应该使用try-with-resources
或显式调用close()
方法来管理资源。
3. 其他方法
wait()
,notify()
,notifyAll()
:这些方法与线程间的通信(等待/通知机制)相关。它们都是final
方法,不能被重写。必须在同步代码块(synchronized block)或同步方法中使用。
4. 总结
方法 | 作用 | 是否需要重写 | 关键点 |
---|---|---|---|
toString() |
返回对象字符串表示 | 强烈建议 | 便于阅读和调试 |
equals(Object) |
判断对象内容是否相等 | 需要时重写 | 比较内容而非地址 |
hashCode() |
返回哈希码 | 重写equals时必须重写 | 遵守与equals的约定 |
getClass() |
获取运行时类 | 不能重写 | 反射基础 |
clone() |
创建对象副本 | 需要时重写 | 需实现 Cloneable ,注意深浅拷贝 |
finalize() |
垃圾回收前清理 | 不应使用 | 已废弃,不可靠 |
理解并正确使用 Object
类的方法,是编写高质量、健壮的Java代码的基础。特别是 equals()
和 hashCode()
的配合使用,是面试和实际开发中的常见考点。