Java源码分析——Object类解析,一切类的源头

2020-09-30 15:44发布

    Java语言类的起始点源于Object类,其它类都直接或间接继承Oject类,可以说Object类是一切类的源头。下面来谈下Object类的内部的编码以及简单的阐述下其中的native本地的方法。
    在Java程序运行的时候,我们不免会想到java中的类怎么进入jvm里面执行,也就是怎么加载进jvm的,在Object类里面有如下定义:

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

    registerNatives方法就是负责这一功能的,它调用了Openjdk的本地方法,将该类注册进jvm中,在Openjdk里面registerNatives方法是由c++来实现的,代码如下

Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}12345

    接下来是getClass方法,该方法的作用是来获取Class类的实例,在这里其实是获取该类的完整名字,什么叫完整的名字呢?比如说Object类,那么它的完整名字是java.lang.Object。要注意的是它也是调用的本地的方法,还需要注意的是该方法的前缀由final属性,也就是说,该方法不可以被重写:

public final native Class<?> getClass();1

    我们可以从其本地代码当中看出,当该类对象为空时,抛出异常,不为空则返回该类的完整名:

Java_java_lang_Object_getClass(JNIEnv *env, jobject this)
{
    if (this == NULL) {
        JNU_ThrowNullPointerException(env, NULL);
        return 0;
    } else {
        return (*env)-&gt;GetObjectClass(env, this);
    }
}123456789

    接着就是哈希编码了:

public native int hashCode(); 1

    每个类都有其特定的哈希编码,我们可以通过两个对象的哈希编码是否相同来判断其是否是一个类的对象。Java中的hashCode的常规协定是:

  1. 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

  2. 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

  3. 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

    equals是个比较有趣的方法,初学者如果一不小心就会弄错,原由是对java底层的源码不熟悉的结果,Object类中的equals用来判断对象的引用是否相等,而其它类都是在判断引用是否相等的前提下再去执行其它的代码:

public boolean equals(Object obj) {     
    return (this == obj);     
    }  123

    clone方法是一个本地的方法,用来复制一个对象,这种复制常常被我们称为浅拷贝,因为它只复制了对象的引用,两个引用指向的是同一个地址,须注意的是,它是protected方法,也就是说要使用它的话只能被继承一次,也就是在自己自定义的类上进行拷贝,因为这样是默认继承Object方法的,其次需注意的是,使用它需要实现一个标记借口,Cloneable该接口里面没有任何方法,只是纯标记接口,不实现会抛CloneNotSupportedException异常:

protected native Object clone() throws CloneNotSupportedException;    1

    toString是用来返回类中数据的,当想要返回某些数据展示给外界时,重写该方法就可以了:

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

    接下来就是线程有关的操作了,调用了本地方法:

  /*唤醒在此对象监视器上等待的单个线程。*/    
    public final native void notify(); 12

    唤醒在此对象监视器上等待的所有线程:

   public final native void notifyAll();  1

    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行:

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

    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待:

 public final native void wait(long timeout) throws InterruptedException; 1

    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待:

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

    关于wait方法需要注意的几点是:

  1. 使线程主动释放对象锁,并进入等待状态,直到它被其他线程通过notify()或notifyAll唤醒或者超过指定的等待时间。

  2. 在调用wait方法前,线程必须获得该对象的对象锁,即:只能在同步方法或同步代码块中调用wait方法,如果当前线程不是锁的持有者,将抛出一个IllegalMonitorStateException异常(是RuntimeException的子类,故不需要捕获)。

  3. wait方法执行完成后,该线程立即释放持有的对象锁(注:不是等到退出synchronized代码块后才释放)。

  4. 该方法应该被使用在一个循环里,因为不在一个循环里的话就不能及时的知道该线程被唤醒。

  5. wait(long timeout)方法,当timeout=0时,需要notify方法唤醒,大于零沉睡后自动醒来

    最后是关于垃圾回收器的方法,当GC确定不存在该对象的更多引用时,会让对象的垃圾回收器调用此方法,程序员一般不会使用该方法:

 protected void finalize() throws Throwable { }    1

    ps:所有的类都会继承Object类,只不过在程序中不会写出来。

作者:suye233

链接:https://blog.csdn.net/hackersuye/article/details/83345052

来源:CSDN
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。