Java - Object类

1. 意义

为什么今天我想说这个类呢,因为作为the root of class hierarchy,我发现我竟没有认认真真好好理解它的内容以及所有方法的意义。这似乎是不应该的。。。。so,补课,重新学习它

定义:

Object对象是Java类层次结构的根类,所有类的超类
所有的对象(包括数组)都实现这个类的方法

2. 方法

JavaSE7API中的Outline

  1. Object()

    构造方法,默认的,没有显示声明

  2. private static native void registerNatives()

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

    很多类中都有的一段JNI代码,用于统一的将当前类的所有native方法映射到相应的C方法上

    比如,这个Object里的这个方法对应的OpenJDK源码(源码相对目录:…\openjdk\jdk\src\share\native\java\lang下)中C代码是

    
    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]));
    }
    
    JNIEXPORT jclass JNICALL
    Java_java_lang_Object_getClass(JNIEnv *env, jobject this)
    {
     if (this == NULL) {
         JNU_ThrowNullPointerException(env, NULL);
         return 0;
     } else {
         return (*env)->GetObjectClass(env, this);
     }
    }
    

    可以看到,这里映射了5个具体的native方法:hashCode、wait、notify、notifyAll、clone和实现了一个方法getClass

  3. public final native Class<?> getClass()

    不可被覆盖的final方法,其返回的是当前内存中的被引用的实际对象的class,而不是字面上看上去的对象的class

    例如,最常见的一道面试题会这样问:

     super.getClass().getName();
     //返回的是什么?
     //    答案并非父类的名字,而是当前this对象的class对象的名字
     //而要获取父类的名字可以如下
     getClass().getSuperClass().getName();
  4. public native int hashCode()

    返回当前对象的hash code,这个方法用于提高hash表的性能(例如java.util.Hashtable提供的hash表)

    这个方法的general contract是:

    1. 同一个对象多此调用hashCode()必须返回相同的整数,前提是对象的equals()方法用到的信息没有被修改
    2. 如果根据equals()方法,两个对象是相等的,那么hashCode必须返回相同的整数
    3. 如果根据equals()方法,两个对象不相等,那么也有可能hashCode相等

    这个

  5. public boolean equals(Object obj)

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

    equals方法指示对象是否“相等”

    Object类中这个equals实现的是对象上差别可能性最大的相等关系,即,对于非空引用x和y,仅当其引用的是同一个对象时才返回true

    equals方法在非空引用上实现相等关系必须满足几个性质:

    1. 自反性:x..equals(x) 必须为true
    2. 对称性:y.equals(x)为true,x.equals(y)也应为true
    3. 传递性:x.equals(y),y.equals(z)那么x.equals(z)也应为true
    4. 一致性:多此调用equals,结果应该一致,在equals所用信息没有被修改的前提下
    5. x.equals(null)必须为false

    如果重写equals方法,通常有必要重写hashCode方法,用以维护hashCode方法的常规协定,来保证equals的对象必须具有相等的hash code

  6. protected native Object clone() throws CloneNotSupportedException

    克隆当前对象生成新的实例

    • 被克隆对象必须实现接口 Cloneable
    • 所有数组都被看做已经实现了Cloneable
    • 这个clone是“浅表 copy”而不是“deep copy”

    shallow copy就是说没有clone源对象的引用成员变量所指向的对象,而是直接使用了源对象的引用

    一道面试题:怎么(浅表copy)clone对象?clone()方法通常都有一行代码,是什么?

    答案:
    实现Cloneable接口并override重写clone()方法;
    super.clone(),按照惯例克隆对象必须通过super.clone()来完成

    代码:

    class A implements Cloneable{
     public Object clone() throws CloneNotSupportedException {
         A cloned = (A) super.clone();
         //cloned.xxx引用成员 = (B) xxx引用成员.clone() //这是deep clone
         return cloned;
     }
    }
  7. public String toString()

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

    方法返回对象的字符串表示。建议所有子类重写此方法

    Object类默认的toString()返回一个字符串,值为:

    getClass().getName() + "@" + Integer.toHexString(hashCode());
  8. public final native void notify()

    唤醒在此对象监视器上waiting的单个线程。如果有很多线程都在此对象上waiting,则会任意选择一个唤醒。线程通过调用wait方法,使自己处于waiting状态

    被唤醒的线程将以常规的方式与其它在该对象上同步的所有线程进行竞争

    notify()方法只能被对象监视器当前所有者线程来调用,一次只能有一个线程拥有对象的监视器。有3种方法,线程可以称为对象监视器的拥有者:

    1. 执行对象的synchronized实例方法
    2. 执行对象的synchronized语句
    3. 对于Class类型的对象,可以执行类的synchronized静态方法
  9. public final native void notifyAll()

    唤醒在此对象监视器上waiting的所有线程,其它参考notify

  10. public final native void wait(long timeout) throws InterruptedException

    使当前线程waiting并进入当前对象监视器的wati set中,直到超出timeout或notify被调用

    注意:
    调用对象的wait()类方法时,对象必须拥有对象监视器的锁,如果没有将抛出异常“IllegalMonitorStateException”。也就是说必须在synchronized语句块中调用(或java.util.concurrent包中类);

    另外:
    调用wait(0),相当于调用wait()会一直被wait
    11和12最终还是调用10这个方法

  11. public final void wait(long timeout, int nanos) throws InterruptedException

    纳秒级别控制wait时间

    最终还是调用

    wait(timeout);
  12. public final void wait() throws InterruptedException

    public final void wait() throws InterruptedException {
        wait(0);
    }
  13. protected void finalize() throws Throwable { }

    当GC确定不存在该对象的更多引用,想要清楚此对象时,GC会调用该方法。子类重写此方法,以处置系统资源或执行其它清除

    你当然可以在GC将要回收时,在finalize方法中重新使此对象对其它线程可用(救下它),但是,finalize()方法的主要目的是:在不可撤销(前面说的操作叫撤销)的要丢弃对象的情况下,给你一个机会让你去执行一些清除操作。例如,输入/输出连接的相关对象的finalize方法可以显示的执行I/O事务,以便在丢弃对象前中断连接

    • finalize被执行后,对象不会立马被丢弃,JVM会再次确定一遍,如果还是“不可达”,才会真正丢弃
    • 对于一个对象,JVM最多只会调用一次finalize方法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值