Java教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言变更,了解Java SE 9及以后版本中更新的语言特性的摘要。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息。
Object类位于java.lang包中,位于类层次结构树的顶部。每个类都是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()方法测试对象的引用是否相等,也就是说,如果比较的对象是同一个对象。
要测试两个对象是否在等价的意义上相等(包含相同的信息),你必须重写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");
}
即使firstBook和secondBook引用两个不同的对象,但此程序显示对象相等。它们被认为是相等的,因为比较的对象包含相同的ISBN号。
如果对于您的类而言,恒等操作符不合适,您应该始终重写equals()方法。
equals(),您必须同时重写hashCode()。
Object类提供了一个回调方法finalize(),当一个对象变为垃圾时,可能会调用该方法。Object的finalize()方法不执行任何操作,您可以重写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()方法返回一个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()方法返回的是对象的哈希码,它是由哈希算法生成的整数值。
根据定义,如果两个对象相等,它们的哈希码也必须相等。如果你重写了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