Object作为超类
java.lang
包中的Object
类位于类层次结构树的顶部,每个类都是Object
类的直接或间接的后代,你使用或编写的每个类都继承Object
的实例方法,你不需要使用任何这些方法,但是,如果你选择这样做,你可能需要使用特定于你的类的代码重写它们,本节中讨论的从Object
继承的方法是:
-
protected Object clone() throws CloneNotSupportedException
创建并返回此对象的副本。 -
public boolean equals(Object obj)
指示某个其他对象是否“等于”此对象。 -
protected void finalize() throws Throwable
垃圾回收器在对象上执行垃圾回收时调用。
集合确定不再有对该对象的引用。 -
public 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
方法。
clone()方法
如果某个类或其中一个超类实现了Cloneable
接口,则可以使用clone()
方法从现有对象创建副本,要创建克隆,请编写:
aCloneableObject.clone();
Object
的此方法实现检查调用clone()
的对象是否实现Cloneable
接口,如果对象没有,则该方法抛出CloneNotSupportedException
异常,稍后的课程将介绍异常处理,目前,你需要知道clone()
必须声明为:
protected Object clone() throws CloneNotSupportedException
或
public Object clone() throws CloneNotSupportedException
如果要编写clone()
方法来覆盖Object
中的方法。
如果调用clone()
的对象确实实现了Cloneable
接口,对象的clone()
方法实现创建与原始对象相同的类的对象,并初始化新对象的成员变量,使其具有与原始对象的相应成员变量相同的值。
使类可克隆的最简单方法是将implements Cloneable
添加到类的声明中,然后你的对象可以调用clone()
方法。
对于某些类,Object
的clone()
方法的默认行为可以正常工作,但是,如果一个对象包含对外部对象的引用,比如说ObjExternal
,则可能需要重写clone()
以获得正确的行为,否则,一个对象对ObjExternal
所做的更改也将在其克隆中可见,这意味着原始对象及其克隆不是独立的 — 要将它们分离,你必须重写clone()
以便它克隆对象和ObjExternal
,然后原始对象引用ObjExternal
,并且克隆引用ObjExternal
的克隆,以便对象及其克隆真正独立。
equals()方法
equals()
方法将两个对象进行相等性比较,如果它们相等则返回true
,Object
类中提供的equals()
方法使用标识运算符(==
)来确定两个对象是否相等。对于原始数据类型,这会给出正确的结果,但是,对于对象,它没有,Object
提供的equals()
方法测试对象引用是否相等 — 即,如果比较的对象是完全相同的对象。
要测试两个对象在等价意义上是否相等(包含相同的信息),必须重写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()
。
finalize()方法
Object
类提供了一个回调方法finalize()
,当它变为垃圾时,可以在对象上调用它,Object
的finalize()
实现什么也没做 — 你可以重写finalize()
来执行清理,例如释放资源。
finalize()
方法可以由系统自动调用,但是什么时候调用,或者即使调用,也是不确定的,因此,你不应该依赖此方法为你进行清理。例如,如果在执行I/O后没有在代码中关闭文件描述符,并且你希望finalize()
为你关闭它们,则可能会耗尽文件描述符。
getClass()方法
你不能重写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()方法
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