Object类 源码分析

首先看看方法:

public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj);
protected native Object clone() throws CloneNotSupportedException;
public String toString();
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;
public final void wait() throws InterruptedException;
protected void finalize() throws Throwable;


1. getClass方法

这是一个native方法,返回的是当前对象的类的字节码。

2. hashCode方法

这是一个native方法,返回的是根据当前对象的物理地址生成的哈希码,目的是为了区分不同的对象,这在一些根据Hash值来存储的集合中很有用。

如果两个对象经过equals比较后,返回true,那么它们的hashCode也必须是相同的;
如果两个对象经过equals比较后,返回false,那么它们的hashCode可以不同,也可以相同。

3. equals方法

比较当前对象是否和某个object相等。如果重写这个方法,需要满足下面的契约:
a. reflexive (反身性)
   => x != null
   x.equals(x) return true

b. symmetric (对称性)
   => x != null && y != null
   if (x.equals(y)) y.equals(x) return true

c. transitive (传递性)
   => x != null && y != null && z != null
   if (x.equals(y) && y.equals(z)) x.equals(z) return true

d. consistent (连贯性)
   => x != null && y != null
   x.equals(y) return false;
   ...
   x.equals(y) return false;

e. x != null
   x.equals(null) return false

4. clone方法

这是一个native方法,创建并返回该对象的拷贝。

对于某个对象x,
x.clone() != x return true // 但这不是绝对的
x.clone().getClass() == x.getClass() return true // 但这不是绝对的

典型情况下:
x.clone().equals(x) return true // 但这不是绝对的

按照惯例,该方法调用suer.clone()。如果这个类和所有它的超类都遵循这个规则,那么:x.clone().getClass() == x.getClass()

按照惯例,拷贝的对象应该和该对象相互独立。为了达到这个目标,在返回之前需要对其中的一个或几个字段进行修改,拷贝组成当前对象的变化部分,然后把引用改成指向拷贝。如果一个类只有原始类型字段或者对不变对象的引用,不需要做这些修改。

过程:
a. 首先如果当前对象的类没有实现Cloneable接口,抛CloneNotSupportedException异常
b. 创建当前对象的类的新实例,用当前对象的内容来初始化所有的字段。所以只是复制了引用,是shallow copy

5. toString方法

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

返回该对象的string表示形式。该表示应该能够表达该对象的信息。最好是所有的子类都重写该方法。

Object的toString方法返回:该对象的类名 + "@" + 该对象hashCode的16进制表示形式

6. notify方法

这是一个native方法,唤醒一个在当前对象监视器上等待的线程。

被唤醒的线程直到当前线程释放锁后才可以执行,并且和其它线程竞争对象的拥有权(没有优先级之分)。

这个方法应该仅仅被拥有对象监视器的线程所调用。

一个线程成为对象的监视器的拥有者的三种方法:
a. 执行该对象上的一个同步(synchronized)方法
b. 执行一个同步在该对象上的代码块
c. 执行该对象的类上的静态同步方法

7. notifyAll方法

这是一个native方法,唤醒所有在当前对象监视器上等待的线程。

和notify类似。

8. wait(long timeout)方法

这是一个native方法,使当前线程等待,直到另外一个线程调用改对象的notify或notifyAll方法,或者等待时间已到。

当前线程必须拥有该对象的监视器。

该方法会让当前线程T进入到当前对象的等待集中,让出当前对象的监视器,T被禁用直到下面情况中的一种发生:
a. 其它线程调用当前对象的notify方法,并且T恰好被选中唤醒
b. 其它线程调用当前对象的notifyAll方法
c. 其它线程暂停T
d. 等待时间已到

被唤醒后,T从等待集中被移除和启用等待线程调度,接着会和其它线程竞争当前对象的拥有权。如果T成功了,就会从wait方法的调用处返回,当前对象和T的同步状态和调用wait时一样。

有种情况是伪唤醒,就是T从wait处返回了,没有出现上面说的4种情况。所以wait方法放在loop块中,确保不是伪唤醒:

synchronized (obj) {
	while (<condition does not hold>)
		obj.wait(timeout);
	... // Perform action appropriate to condition
}

如果在wait之前或wait的时候,当前线程被中断了,那么直到当前线程恢复时才会抛InterruptedException。

wait方法会使当前线程让出当前对象的拥有权,但是不会让出同步的其它对象。

该方法必须是在当前线程是当前对象的拥有时才可以调用。

9. wait(long timeout, int nanos)方法

    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException("nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

看到该方法的签名,以为nanos会提供更高精度的控制。但是代码将nanos四舍五入到timeout,调用wait(timeout)方法。

10. wait()方法

    public final void wait() throws InterruptedException {
        wait(0);
    }

这里的参数0表示没有时间限制。

11. finalize方法

垃圾回收器觉得该对象没有被其它任何存在的线程引用时会调用该方法。子类可以通过复写该方法来达到资源释放。

Java不能保证什么线程会来调用某个对象的finalize方法。可以保证的是,当finalize被调用时,调用finalize的线程不会拥有用户可见的同步锁。在方法调用过程中出现的异常会被忽略并且方法调用会终止。

任何对象的finalize方法只会被调用一次。

你可能感兴趣的:(java,object,equals,HashCode,clone)