天天看点

Java Object类源码阅读

/**
 * Object类是类层次结构的根类。Object类是每一个类的超类。所有对象,包括数组,
 * 都实现了这个类的方法。
 */
public class Object1 { Object

    private static native void registerNatives();
    static {
        registerNatives();
    }

    /**
     * 返回这个Object的运行时Class对象。这个Class对象被所代表的类的static synchronized
     * 方法锁定。
     *
     * 实际的返回类型是Class<? extends |X|>,|X|是the erasure of 
     * the static type of the expression(什么意思?),这个表达时调用
     * getClass方法。例如,这个代码片段不需要造型:
     * Number n = 0;
     * Class<? extends Number> c = n.getClass();
     */
    public final native Class<?> getClass();

    /**
     * 返回这个对象的哈希值。支持这个方法是为了提高哈希表的性能,例如HashMap。
     * 
     * 关于hashCode通常的约定是:
     * 在一个Java应用程序执行期间,无论何时,在相同的对象上调用这个方法多次,都将返回相同的
     * 整数,前提是在这个对象上用于equals比较的信息没有改变。在应用程序的不同次执行中,这个
     * 返回值不必保持一致。
     * 
     * 如果通过equals(Object)方法比较,两个对象相等,那么在这两个对象上调用hashCode
     * 方法将产生相同的整型值。
     * 
     * 通过equals(Object)方法比较,两个对象不相等,并不要求在这两个对象上调用hashCode
     * 方法也有不同的返回值。然而,程序员应该注意到,对不相等的对象产生不同的整型值可能提高
     * 哈希表的执行性能。
     * 
     * 实际上,被Object类定义的hashCode方法对不同的对象确实返回不同的整数。(这是通过
     * 把对象的内部地址转化为一个整数来实现的,但是这个实现技巧不被Java编程语言需要。)
     */
    public native int hashCode();

    /**
     * 指示这个其它对象是否和这个对象相等。
     * 
     * equals方法实现非null对象引用之间的相等关系
     * 
     * 它是反身的:对于任何非null引用值x,x.equals(x)应该返回true。
     * 
     * 它是对称的:对于任何非null引用值x 和 y, 当且仅当y.equals(x)返回true时,
     * x.equals(y)才返回true。
     * 
     * 它是传递的:对于任何非null引用值,x,y和z,如果x.equals(y)和
     * y.equals(z)返回true,那么x.equals(z)也应该返回true。
     * 
     * 它是一致的:对任何非null引用值x和y,多次调用x.equals(y)一直返回true或者false,前提
     * 是对象上被用在相等比较上的信息没有被修改。
     * 
     * 对于任何非null引用值x,x.equals(null)应该返回false。
     * 
     * Object类的equals方法对象上差别可能性最大的相等关系。也就是说,对于任何
     * 非null引用值x和y,当且仅当这个x和y引用同一个对象时,这个方法才返回true(
     * x==y是true)
     * 
     * 注意,无论何时重写这个方法都应该重写hashCode方法,来保证hashCode方法的约定,约定
     * 指出相等的对象必须有相等的哈希值。
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

    /**
     * 创建这个对象的一个拷贝。复制的精确意思依赖于这个对象的类。对于任何一个对象x,通用
     * 目的是:
     * x.clone() != x的值为true,
     * x.clone().getClass() == x.getClass()的值为真,
     * 但是这些不是绝对需要的。
     * 典型的,x.clone().equals(x)的值为true,这也不是绝对需要的。
     * 
     * 按照惯例,返回的对象应该调用super.clone获得。如果一个类和它的所有超类(除Object)
     * 都遵从这个约定,那么:
     * x.clone().getClass() == x.getClass()
     * 
     * 按照约定,被这个方法返回的对象应该独立于被拷贝的对象。为了实现这个独立性,修改一个或多个
     * 被返回对象的域可能是必要的。典型的,这意味着复制包含被复制对象的内部“深度结构”的可变对象,
     * 并且使用副本的引用替换这些对象的引用。如果一个类只包含基本类型域或者不可变对象的应用,那么通过
     * super.clone返回的对象中没有域需要被修改。
     * 
     * Object类的clone方法执行一个指定的克隆操作。首先,如果对象的类没有实现接口
     * Cloneable,那么CloneNotSupportedException将被抛出。注意,所有数组
     * 都实现了Cloneable接口,一个类型为T[]的数组的clone方法的返回类型是T[],
     * T可以是基本类型,也可以是引用类型。否则,这个方法创建这个对象的类的一个新
     * 实例,并且通过这个对象的相关域初始化所有的域,就像赋值一样;这些域的内容没有自我复制。
     * 因此,这个方法执行这个对象的浅复制,而不是深度复制。
     * 
     * Object类自己没有实现Cloneable接口,所以在Object类的对象上调用clone将会抛出一个
     * 运行时异常。
     */
    protected native Object clone() throws CloneNotSupportedException;

    /**
     * 返回这个对象的字符串表示。一般的,toString方法返回表示这个对象的字符串。返回的
     * 结果应该是简明的但是带有有用信息的表示,并且是易于人阅读的。
     * 
     * 建议所有子类都是重写这个方法。
     * 
     * Object类的toString方法返回一个字符串,这个字符串由这个对象的类名,@符号,和
     * 这个对象的哈希值的无符号十六进制表示。
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    /**
     * 唤醒一个正在等待这个对象的监视器的线程。如果一些线程正在这个对象上等待,它们中的一个
     * 将会被唤醒。哪一个被唤醒是不确定的。通过调用一个wait方法,线程在一个对象的监视器上
     * 等待。
     * 
     * 直到现在占有这个对象锁的线程放弃锁,被唤醒的线程才可能被处理。被唤醒的线程和其它一直活跃
     * 并也在竞争这个对象上同步的线程一样竞争获得处理的机会,例如,被唤醒的线程在作为下一个
     * 持有该对象锁方面没有可靠的优先级或者优势。
     * 
     * 这个方法只能被这个对象的监视器的拥有者调用。一个线程以下面三种方式之一成为对象监视器
     * 的拥有者:
     * 通过执行这个对象的一个synchronized实例方法
     * 
     * 通过执行在这个对象上同步的语句
     * 
     * 对于Class类的对象,通过执行这个类的同步静态方法。
     * 
     * 在同一时间,只有一个线程能拥有对象的监视器
     */
    public final native void notify();

    /**
     * 唤醒所有等待这个对象的监视器的线程。一个线程通过调用wait方法在一个对象的监视器上等待。
     */
    public final native void notifyAll();

    /**
     * 导致现在的线程去等待,直到另一个线程对这个对象调用notify()或者notifyAll()方法,或者指定
     * 的时间段已经过去。
     * 
     * 现在的线程必须拥有这个对象的监视器。
     * 
     * 这个方法导致当前线程(线程 T)把它自己放在这个对象的等待集上,然后放弃这个对象上的所有
     * 等待声明。出于线程调度的目的,线程T变得不可用的,并且休眠的,直到下面四种情况之一发生
     * 时:
     * 其它线程对这个对象调用notify方法,而且线程T刚好被选中为被激活的线程。
     * 其它线程对这个对象调用notifyAll方法。
     * 其它线程中断线程T。
     * 指定数量的时间已经过去。如果timeout是0,时间不被考虑,线程一直等待直到被通知。
     * 
     * 线程T从这个对象的等待集中移除,而且对线程调度程序重新变得可用。线程T以常规的方法与其它线程
     * 竞争在这个对象上同步的权利;一旦它获得这个对象的控制,所有在这个对象上的同步声明将被恢复到
     * 之前的状态,也就是说,恢复到wait方法调用时的状态。因此,从wait方法返回时,这个对象和
     * 线程T的同步状态和wait方法被调用时的状态一样。
     * 
     * 在没有被通知,中断,或者超时时,一个线程依然可以被唤醒,即所谓的虚假唤醒。尽管在实际中
     * 这种情况很少发生,但是应用程序必须通过测试本应该导致线程被唤醒的条件防止其发生,如果
     * 条件没有被满足,线程就应该继续等待。换句话说,等待应该总是发生在循环中,就像这个:
     *     synchronized (obj) {
     *         while (condition does not hold)
     *             obj.wait(timeout);
     *         ... // Perform action appropriate to condition
     *     }
     *
     * 如果当前线程在等待之前或之中被其它线程中断,就会抛出InterruptedException。直到这个对象
     * 像上面描述那样恢复到锁定状态,这个异常才会抛出。
     * 
     * 注意,就像wait方法把当前线程放进这个对象的等待集中一样,它只能解除这个对象的锁定;当前
     * 线程在其上同步的其它对象依旧锁定,当这个线程等待时。
     * 
     * 这个方法应该被这个对象的监视器的拥有线程调用。
     */
    public final native void wait(long timeout) throws InterruptedException;

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


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

    /**
     * 当垃圾回收器得知没有对这个对象的引用时,这垃圾回收器调用这个方法。子类重写这个方法
     * 去处理系统资源或者执行其他清理。
     * 
     * finalize的一般约定是,如果活着的线程不能通过任何方法访问到这个对象时,这个方法被
     * 调用,除非是其它准备终结的对象或者类的终结的结果。finalize方法可能采取任何动作,,
     * 包括让这个对象对其它线程可用;但是,finalize通常的目的是,在这个对象被丢弃之前
     * 执行清理动作。例如,代表一个输入输出连接的对象的finalize方法可能执行清晰的I/O事物来
     * 中断连接,在这个对象被永久丢弃之前。
     * 
     * Object类的finalize方法执行非特殊的动作;它仅仅正常地返回。Object类的之类可以重写
     * 这个方法。
     * 
     * Java语言不保证哪一个线程对任何给定对象调用finalize方法。但是,可以保证调用finalize
     * 方法的线程不会持有用户可见的同步锁,当finalize被调用时。如果finalize方法抛出
     * 一个未捕获异常,异常将被忽略,对象的结束行为将被终止。
     * 
     * 在一个对象上调用finalize方法后,没有进一步的动作被执行,直到Java虚拟机再次得知活着的
     * 线程没有任何方法可以访问到这个对象,包括准备结束的其它对象或者类的可能的动作,在这时,
     * 对象可能被丢弃。
     * 
     * 对于任何给定的对象,Java虚拟机只调用一次finalize方法。
     */
    protected void finalize() throws Throwable { }
}