jdk源码之 object类

3,829 阅读5分钟
package java.lang;

public class Object {

    // 该方法为一个原生态的方法,实质是通过JNI调用底层系统,它未提供方法体,通过一个静态块进行调用,
    // 要为自己的类注册本地函数,必须RegisterNatives从你自己的库中的本机代码调用JNI函数。
    private static native void registerNatives();

    // 静态代码块就是一个类在初始化过程中必定会执行的内容,所以在这里执行,
    // 它进行一些跟系统有关的方法调用,而这个方法的实现就在java.dll中,
    // 通常,为了让JVM找到本地函数,它们必须以某种方式命名。
    // 例如,java.lang.Object.registerNatives对应的C函数被命名Java_java_lang_Object_registerNatives。
    // 通过使用registerNatives(或者说,JNI函数RegisterNatives),可以任意指定C函数。
    // 对JNI研究较少,该方法暂时了解到这,

    /**
     static JNINativeMethod methods[] = {
          {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
          {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
          {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
          {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
          {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
      };

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

    static {
        registerNatives();
    }

   // 该方法同样为一个原生态方法,返回运行时class对象,
   // 当我们需要得到当前运行时class对象是,就可以调用类的getClass()方法;
    public final native Class<?> getClass();

    /*  
        返回一个对象的哈希码值,提到hashCode,就想到了hash算法,以用来提高查询效率。其实
    在java中hashcode主要作用是配合基于散列的集合一起正常运行,如hashMap,hashSet,hashTable。
    因为集合中不允许出现相同的对象,当向集合中插入相同的对象时,通过对象的hashCode来进行对
    比,也许大家会想到使用Object类提供的equals方法,或者自定义equals方法进行逐一比较,然而
    当集合中的数据不是很多的时候可能体现不出来,但是数据量较大时,它的效率很底下,所以我们
    首先想到的是先进行hashCode比较,hashCode相等时再进行equals进行比较,这样就提高了插入的
    效率。
        直白点说:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地
    址,对象的字段等)映射成一个数值 ,这个数值称作为散列值。用来初步判断对象是否相等,不同
    的对象可能会生成相同的 hashcode值。虽然不能根据hashcode值判断两个对象是否相等。但是可以
    直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象
    。如果要判断两个对象是否真正相等,必须通过equals方法,
    */
    public native int hashCode();

    // equals方法,在实际开发中用到的非常多,Object类的equals方法,
    // 这里方法体的代码的作用是判断当前对象和传入的对象是否引用为同一对象,
    // 是则返回true,否则返回false
    //      1)、对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;
    //    2)、如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;
    //    3)、两个对象的hashcode值相等,则equals方法得到的结果未知;
    public boolean equals(Object obj) {
        return (this == obj);
    }

    //  clone从字面上的意思理解,就是复制,把原对象的内容复制到新对象中去,
    //  日常开发中,使用的最多的就是数组的复制,提到数组的复制,还要对象之间的拷贝,
    //  比如把vo中的对象拷贝到实体bean中去,提到复制,不得不说下,深复制、浅复制的区别了:
    //
    //  浅层复制:被复制的对象的所有成员属性都有与原来的对象相同的值,
    //            而所有的对其他对象的引用仍然指向原来的对象。
    //            换言之,浅层复制仅仅复制所考虑的对象,而不复制它所引用的对象;

    //  深层复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。
    //            那些引用其他对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。
    //            换言之,深层复制要复制的对象引用的对象都复制一遍。

    //  简而言之:深复制就是对象内容、对象复制了新的对象(重新生成内存地址),而浅复制只是复制对象的内容,对象的引用还是原来的引用。
    protected native Object clone() throws CloneNotSupportedException;



    // 从方法的内容上看,就是返回当前对象的名称+“@”+调用Integer的方法转为一个无符号数,
    // 实际情况要调用是会重写toString的
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }


    // 调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,
    // 如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程.
    public final native void notify();

    // 唤醒在此对象监视器上等待的所有线程。
    public final native void notifyAll();

    // 线程等待;
    // 注意区分sleep方法(sleep是Thead的方法)
    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 > 0) {
            timeout++;
        }

        wait(timeout);
    }

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

    // 一旦垃圾回收器准备释放对象所占的内存空间, 如果对象覆盖了finalize()并且函数体内不能是空的,
    // 就会首先调用对象的finalize(),  然后在下一次垃圾回收动作发生的时候真正收回对象所占的空间.
    //  看jvm时再补充更详细的
    protected void finalize() throws Throwable {

    }

}