Java教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言变更,了解Java SE 9及以后版本中更新的语言特性的摘要。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息。
Object
类位于java.lang
包中,位于类层次结构树的顶部。每个类都是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
方法。
如果一个类或其超类实现了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