【JAVA源码学习】Object类

Object类是类层次结构的根,它是 Java其他所有类的超类。

在介绍 Object源码前,补充 native关键字:

native关键词修饰的方法是一个原生态方法(本地方法),方法对应的实现不是在当前文件,具体是用C(C++)在DLL中实现的,然后通过JNI调用

以下的源码是 jdk1.8 版本:

public class Object {

     // 本地方法,作用为注册一些本地方法
    private static native void registerNatives();
    
     // 对象初始化时自动调用此方法
    static {
        registerNatives();
    }
    
     // 本地方法,返回当前的运行时类
    public final native Class<?> getClass();
    
     /**
     * 本地方法,计算哈希值,相关的三个规定:
     * 1. 在应用程序执行期间,对于同一对象,不进行修改的前提下,两次调用该方法得到的哈希值必须相同
     * 2. 对于执行 equals()方法返回为 true的两个对象,执行 hashCode()方法,需返回相同的结果
     * 3. 如果根据 equals()方法,两个对象不相等,执行 hashCode()方法,返回结果不必一定不同,但不同可以提升哈希的性能
     * @return 该对象的哈希值
     */
    public native int hashCode();
    
     /**
     * 用于判断两个对象的内容是否相等,具有以下特点:
     * 1. reflexive(自反性),x.equals(x)的结果一定为 true
     * 2. symmetric(对称性),x.equals(y)为 true,当且仅当 y.equals(x)为 true
     * 3. transitive(传递性),当 x.equals(y),y.equals(z),可以推出:x.equals(z)
     * 4. consistent(一致性),对于 x.equals(y),在不修改 x,y的前提下,调用几次的结果是不变的
     * 5. 当参数为 null,返回 false
     * 同时要注意,当这个方法被重写时, hashCode()也应该同步被重写
     * @return true代表对象与传入参数相等
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

     /**
     * 创建并返回该对象的副本,一般要求(非必要):
     * 1. x.clone() != x返回 true
     * 2. x.clone().getClass() == x.getClass()返回 true
     * 3. x.clone().equals(x) true
     * 
     * 注意,Object自身并没有实现 Cloneable接口,因此不能对其调用 clone方法
     * @return 一个复制的实例
     */
    protected native Object clone() throws CloneNotSupportedException;

     // 返回该对象的字符串表示
     // 获取字节码文件的对应全路径名例如java.lang.Object,并将哈希值转成16进制数格式的字符串输出
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    
     // 本地方法,唤醒在此对象监视器上等待的单个线程
    public final native void notify();

     // 本地方法,唤醒在此对象监视器上等待的所有线程
    public final native void notifyAll();
    
     /**
     * 本地方法,使当前线程等待,直到被 notify()或 notifyAll()方法唤醒,或者过去了指定的时间
     * @param 等待的最大毫秒数
     */
    public final native void wait(long timeout) throws InterruptedException;

     * 本地方法,使当前线程等待,直到被 notify()notifyAll()方法唤醒,或者过去了指定的时间
     * @param  timeout 等待的最大毫秒数
     * @param  nanos   额外的时间,以纳秒为范围 0-999999     
     */
    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");
        }

        // 当传入的纳秒数合法时,将毫秒数 +1
        if (nanos > 0) {
            timeout++;
        }

        // 调用 wait()函数,等待时间为原传入最大等待毫秒数 +1
        wait(timeout);
    }

     // 本地方法,使当前线程等待,直到被 notify()或 notifyAll()方法唤醒
    public final void wait() throws InterruptedException {
        wait(0);
    }

     // 本地方法,当垃圾回收期确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
    protected void finalize() throws Throwable { }
}


对于上面的源代码,有一个地方我个人比较不解:
    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 > 0) {
            timeout++;
        }

        wait(timeout);
    }

关键在与纳秒数,而 1000,000 ns = 1 ms,相当于我们传入的纳秒数,范围从 [1ns, 1ms),但对于上面的代码,传入 100ns,跟 500ns,并没有什么不同,所以说明源码并不支持纳秒级别的休眠时间。

而对比 jdk1.6的源代码:

    public final void wait(long timeout, int nanos) throws nterruptedException {
        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);
    }

当超过半毫秒,或者当毫秒数为 0,纳秒数不为 0时,加 1。对于这种,800ns跟 900ns也没有不同,个人推荐纳秒级别过于低,因此对纳秒进行粗略的处理,但不太能理解从 jdk1.6到 jdk1.8对这个函数的改动有什么意义。欢迎有其他想法的博友在下方留言交流。

你可能感兴趣的:(JAVA源码学习)