Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
java.lang 包中的 Object 类位于类层次结构树的顶部。每个类都是 Object 类的后代,直接或间接的。你使用或编写的每个类都继承 Object 的实例方法。你不需要使用任何这些方法,但是,如果你选择这样做,则可能需要使用特定于你的类的代码覆盖它们。本节中讨论的继承自 Object 的方法是:
protected Object clone() throws CloneNotSupportedExceptionpublic boolean equals(Object obj)protected void finalize() throws Throwablepublic final Class getClass()public int hashCode()public String toString()Object 的 notify, notifyAll 和 wait 方法都在一个程序中同步独立运行的线程的活动中起作用,将在后面的课程中讨论,这里不会涉及。这些方法有五种:
public final void notify()public final void notifyAll()public final void wait()public final void wait(long timeout)public final void wait(long timeout, int nanos)clone 方法。
如果某个类或其某个超类实现 Cloneable 接口,则可以使用 clone() 方法从现有对象创建副本。要创建克隆,请编写:
aCloneableObject.clone();
Object 的此方法的实现检查以查看调用 clone() 的对象是否实现 Cloneable 接口。如果对象没有,则该方法抛出 CloneNotSupportedException 异常。稍后的课程将介绍异常处理。目前,你需要知道 clone() 必须声明为
protected Object clone() throws CloneNotSupportedException
或:
public Object clone() throws CloneNotSupportedException
如果要编写 clone() 方法来覆盖 Object 中的方法。
如果调用 clone() 的对象确实实现了 Cloneable 接口,那么 Object 的 clone() 方法创建与原始对象相同的类的对象,并初始化新对象的成员变量,使其具有与原始对象的相应成员变量相同的值。
使类可克隆的最简单方法是将 implements Cloneable 添加到类的声明中。那么你的对象可以调用 clone() 方法。
对于某些类,Object 的 clone() 方法的默认行为可以正常工作。但是,如果对象包含对外部对象的引用,例如 ObjExternal,则可能需要覆盖 clone() 以获得正确的行为。否则,一个对象所做的关于 ObjExternal 的更改也将在其克隆中可见。这意味着原始对象及其克隆不是独立的 - 要解耦它们,必须覆盖 clone() 以便克隆对象 和 ObjExternal。然后原始对象引用 ObjExternal,并且克隆引用 ObjExternal 的克隆,以便对象及其克隆真正独立。
equals() 方法比较两个对象是否相等,如果它们相等则返回 true。Object 类中提供的 equals() 方法使用相等运算符(==)来确定两个对象是否相等。对于基本数据类型,这会给出正确的结果。但是,对于对象,它没有。Object 提供的 equals() 方法测试对象 references (引用) 是否相等 也就是说,比较的对象是否是完全相同的对象。
要测试两个对象在 equivalency (等价)(包含相同信息)的意义上是否相等,必须覆盖 equals() 方法。以下是覆盖 equals() 的 Book 类的示例:
public class Book {
...
public boolean equals(Object obj) {
if (obj instanceof Book)
return ISBN.equals((Book)obj.getISBN());
else
return false;
}
}
考虑这个代码来测试 Book 类的两个实例是否相等:
// Swing Tutorial, 2nd edition
Book firstBook = new Book("0201914670");
Book secondBook = new Book("0201914670");
if (firstBook.equals(secondBook)) {
System.out.println("objects are equal");
} else {
System.out.println("objects are not equal");
}
即使 firstBook 和 secondBook 引用两个不同的对象,此程序仍显示 objects are equal。它们被认为是相同的,因为比较的对象包含相同的 ISBN 号。
如果相等运算符不适合你的类,则应始终覆盖 equals() 方法。
equals(),则还必须覆盖 hashCode()。
Object 类提供了一个回调方法 finalize(),当对象变为垃圾时,可能 调用。Object 的 finalize() 的实现什么都没做 你可以覆盖 finalize() 进行清理,例如释放资源。
finalize() 方法 可能由系统自动调用,但是它何时被调用,或者它是否被调用,是不确定的。因此,你不应该依赖此方法为你进行清理。例如,如果在执行 I/O 后未在代码中关闭文件描述符,并且希望 finalize() 为你关闭它们,则可能会 run out of 文件描述符。
你无法覆盖 getClass。
getClass() 方法返回一个 Class 对象,该对象具有可用于获取有关类的信息的方法,例如其名称(getSimpleName()),它的超类(getSuperclass()),以及它实现的接口(getInterfaces())。例如,以下方法获取并显示对象的类名:
void printClassName(Object obj) {
System.out.println("The object's" + " class is " +
obj.getClass().getSimpleName());
}
java.lang 包中的 Class 类具有大量方法(超过 50 个)。例如,你可以测试该类是否为注解(isAnnotation()),接口(isInterface())或枚举(isEnum())。你可以看到对象的字段是什么(getFields())或其方法是什么(getMethods())等等。
hashCode() 返回的值是对象的哈希码,它是十六进制的对象的内存地址。
根据定义,如果两个对象相等,则它们的哈希码 必须也 相等。如果覆盖 equals() 方法,更改两个对象的等效方式,则 Object 的 hashCode() 的实现不再有效。因此,如果覆盖 equals() 方法,则还必须覆盖 hashCode() 方法。
你应该始终考虑覆盖类中的 toString() 方法。
Object 的 toString() 方法返回对象的 String 表示,这对于调试非常有用。对象的 String 表示完全取决于对象,这就是你需要在类中覆盖 toString() 的原因。
你可以使用 toString() 以及 System.out.println() 来显示对象的文本表示形式,例如 Book 的实例:
System.out.println(firstBook.toString());
对于正确覆盖的 toString() 方法,打印一些有用的东西,如下所示:
ISBN: 0201914670; The Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition