5.2.6、作为父类的Object

这篇Java教程基于JDK1.8。教程中的示例和实践不会使用未来发行版中的优化建议。
5.2.6、作为父类的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类中的notifynotifyAllwait 方法在线程同步活动中发挥作用。这将在后续的教程中予以讨论,本节不包含该内容。一共有5个这样的方法:

  • 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();

上面的实现会检查调用clone()方法的对象是否有实现Cloneable 接口。如果没有实现,方法将抛出CloneNotSupportedException的异常。异常处理将在后续的教程中讨论。当你想重写Object类的*clone()*方法,你可以用如下的方式来声明:

protected Object clone() throws CloneNotSupportedException

public Object clone() throws CloneNotSupportedException

如果调用clone()方法的对象实现了Cloneable接口,Object类的*clone()*方法实现了根据原对象创建同类型的对象并根据原对象的成员变量来初始化新对象的成员变量。

让类可复制的最简单办法就是在类声明上实现Cloneable 接口。对象可以调用*clone()*方法。

对一些类来说,Objectclone()方法默认行为能工作的很好。然而,对于持有外部对象引用的对象(暂且称为ObjExternal)来说,需要重写clone()方法来获得正确的行为。否则, 对象的ObjExternal发生改变,其拷贝对象也能看到该变化。这意味着原始对象和拷贝对象没有独立开来—为了解耦,你必须重写clone()方法,拷贝该对象和ObjExternal。这样原对象引用ObjExternal,拷贝对象引用ObjExternal的拷贝,这时对象和它的拷贝之间是独立的了。

equals()方法

equals()方法比较对象的相等性,他们相等就返回trueObject类提供的equals()方法使用==来判断两个对象是否相等。对原始类型来说,这没有问题。但对对象来说,这将得到错误的结果。Object类中的equals方法验证对象引用是否相等—即比较的两个对象是否是同一个。

为验证两个对象在语义上的相等性,你必须重写equals()方法。下面是Book类重写了*equals()*方法的示例:

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");
}

程序打印 objects are equal 即使 firstBooksecondBook 引用了两个不同的对象。他们被认为是相等的因为拥有同样的ISBN。

当类的标识符不合适时你总是应该重写它的 equals() 方法。

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() 方法。

ObjecttoString() 方法返回对象的字符串描述,这在调试阶段非常有用。对象的字符串描述依赖整个对象,这也是你需要重写toString() 的原因。

可以和System.out.println() 配合使用 toString() 来打印对象的文本描述,比如Book实例:

System.out.println(firstBook.toString());

因为重写了toString() 方法,将会打印非常有用的信息,如下:

ISBN: 0201914670; The Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值