文档

Java™ 教程
隐藏目录
Object作为超类
路径:学习Java语言
课程:接口和继承
章节:继承

作为超类的对象

Object类位于java.lang包中,位于类层次结构树的顶部。每个类都是Object类的子孙类,直接或间接地。您使用或编写的每个类都会继承Object的实例方法。您不需要使用这些方法,但如果选择使用,则可能需要使用特定于您的类的代码来覆盖它们。本节中讨论的从Object继承的方法有:

ObjectnotifynotifyAllwait方法在程序中同步独立运行的线程的活动中发挥作用,这将在后面的课程中讨论,这里不涉及。这些方法总共有五个:


注意: 这些方法中有一些微妙的方面,特别是clone方法。

clone()方法

如果一个类或其超类实现了Cloneable接口,您可以使用clone()方法从现有对象创建副本。要创建一个克隆对象,您可以编写:

aCloneableObject.clone();

Object的此方法的实现会检查调用clone()的对象是否实现了Cloneable接口。如果对象没有实现该接口,该方法会抛出CloneNotSupportedException异常。异常处理将在后面的课程中介绍。目前,您需要知道clone()必须声明为

protected Object clone() throws CloneNotSupportedException

或者:

public Object clone() throws CloneNotSupportedException

如果你要编写一个clone()方法来覆盖Object中的方法。

如果调用clone()的对象实现了Cloneable接口,Objectclone()方法会创建一个与原始对象相同类的对象,并将新对象的成员变量初始化为与原始对象相同的值。

使你的类可克隆的最简单方法是在类的声明中添加implements Cloneable,然后你的对象可以调用clone()方法。

对于一些类来说,Objectclone()方法的默认行为就足够了。然而,如果一个对象包含对外部对象的引用,比如ObjExternal,你可能需要重写clone()方法以获得正确的行为。否则,一个对象所做的对ObjExternal的更改也会在其克隆中可见。这意味着原始对象和它的克隆不是独立的,为了解耦它们,你必须重写clone()方法,使其克隆对象ObjExternal。然后原始对象引用ObjExternal,克隆引用ObjExternal的克隆,这样对象和它的克隆就是真正独立的。

equals()方法

equals()方法比较两个对象是否相等,并在它们相等时返回true。在Object类中提供的equals()方法使用身份运算符(==)来判断两个对象是否相等。对于基本数据类型,这可以得到正确的结果。但对于对象来说,却不行。Object提供的equals()方法测试对象的引用是否相等,也就是说,如果比较的对象是同一个对象。

要测试两个对象是否在等价的意义上相等(包含相同的信息),你必须重写equals()方法。下面是一个重写equals()方法的Book类的示例:

public class Book {
    String ISBN;
    
    public String getISBN() { 
        return ISBN;
    }
    
    public boolean equals(Object obj) {
        if (obj instanceof Book)
            return ISBN.equals((Book)obj.getISBN()); 
        else
            return false;
    }
}

考虑下面的代码,它测试了两个Book类的实例是否相等:

// Swing教程,第2版
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");
}

即使firstBooksecondBook引用两个不同的对象,但此程序显示对象相等。它们被认为是相等的,因为比较的对象包含相同的ISBN号。

如果对于您的类而言,恒等操作符不合适,您应该始终重写equals()方法。


注意: 如果您重写equals(),您必须同时重写hashCode()

finalize()方法

Object类提供了一个回调方法finalize(),当一个对象变为垃圾时,可能会调用该方法。Objectfinalize()方法不执行任何操作,您可以重写finalize()方法来进行清理,例如释放资源。

finalize()方法可能会由系统自动调用,但是何时调用,甚至是否调用都不确定。因此,不要依赖此方法来进行清理。例如,如果在执行I/O操作后,您没有关闭文件描述符,并且希望finalize()来关闭它们,可能会导致文件描述符用尽。相反,使用try-with resources语句来自动关闭应用程序的资源。请参阅try-with-resources语句Java Platform,Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide中的Finalization and Weak, Soft, and Phantom References

getClass()方法

您无法重写getClass

getClass()方法返回一个Class对象,该对象具有用于获取关于类的信息的方法,例如类名(getSimpleName()),其父类(getSuperclass())和它实现的接口(getInterfaces())。例如,以下方法获取并显示对象的类名:

void printClassName(Object obj) {
    System.out.println("The object's" + " class is " +
        obj.getClass().getSimpleName());
}

Class类位于java.lang包中,拥有大量的方法(超过50个)。例如,您可以测试类是否为注解(isAnnotation()),接口(isInterface())或枚举(isEnum())。您可以查看对象的字段(getFields())或方法(getMethods()),等等。

hashCode()方法

hashCode()方法返回的是对象的哈希码,它是由哈希算法生成的整数值。

根据定义,如果两个对象相等,它们的哈希码也必须相等。如果你重写了equals()方法,你改变了两个对象的比较方式,Object类中的hashCode()方法就不再有效。因此,如果你重写了equals()方法,你也必须同时重写hashCode()方法。

toString()方法

你应该始终考虑在你的类中重写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

上一页: 使用关键字super
下一页: 编写最终类和方法