Object详解

Object类是所有类的父类(包括数组),Object类中共有12个方法(除了init和cinit以外)。

一个静态本地方法registerNatives,在类被加载时执行。
5个方法可以被子类覆盖(也在vtable中)—hashCode(),equals(Object obj),clone(),toString(),finalize()。

6个final的方法,基本逻辑都是由本地方法实现,getClass(),notify(),notifyAll(),wait(long timeout),wait(long timeout, int nanos),wait()


registerNatives方法,作用是通过类加载器,加载一些本地方法到jvm中。
Object类在被加载时,会加载下面的methods中的那些本地方法到jvm中。

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

public final native Class<?> getClass();

这个方法返回的是类的Class对象,具体值取决于调用这个方法的对象。关于Class对象在jvm中的作用,在Java虚拟机第十篇有描述


public native int hashCode();

返回一个对象的哈希值,主要服务于HashMap的hash tables。

hash值需要遵守的约定:
  • 一致性(consistent),在程序的一次执行过程中,对同一个对象必须一致地返回同一个整数。
  • 如果两个对象通过equals(Object)比较,结果相等,那么对这两个对象分别调用hashCode方法应该产生相同的整数结果。
  • 如果两个对象通过java.lang.Object.equals(java.lang.Ojbect)比较,结果不相等,不必保证对这两个对象分别调用hashCode也返回两个不相同的整数。虽然如此,但是如果2个对象不相等,那么返回不同的哈希值有助于哈希表的存储。典型实现是把一个对象的地址转换成整数。

public boolean equals(Object obj)

判断2个对象是否相等,默认实现是判断引用是否相等。
一般来说,如果覆盖了equals方法,那么需要覆盖hashcode方法,用于维持相等对象必须有相等的hashcode这一约束。


protected native Object clone() throws CloneNotSupportedException;

创建并返回这个对象的副本,根据约定,这个方法应该调用super.clone()。

根据约定,拷贝的对象应该是独立于当前对象的(也就是说当前对象的修改,不应该影响到拷贝的对象),对于复杂的结构,需要对内部引用的对象也拷贝一次。也就是说默认实现是浅拷贝的,深拷贝需要自己做处理。比如有一个hashMap,则需要先把hashMap复制一个,再把里面的内容都复制一遍。

如果想调用clone方法,需要这个类实现Cloneable接口,否则抛出java.lang.CloneNotSupportedException异常。
所有的数组默认实现了 Cloneable接口。


public String toString()

推荐所有的子类都覆盖这个方法,默认实现返回类名和对象哈希值的十六进制。

扫描二维码关注公众号,回复: 4058355 查看本文章

public final native void notify();

唤醒等待在这个对象的监视器上的一个线程,如果很多线程在等待,那么其中一个会被唤醒,具体哪个线程被唤醒取决于具体实现。
(一个线程调用某个对象的wait方法后,会在这个对象的监视器上等待。)
一个对象应该先持有这个对象的监视器(执行对象的同步方法或者同步块;对于Class对象,执行静态同步方法),然后才能调用这个方法。

如果当前线程没有持有指定对象的锁,却调用了notify方法,会抛出IllegalMonitorStateException异常。


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

当前线程阻塞指定时间,直到时间到了,或者被其它线程notify。这个方法会释放它持有的所有的锁。
wait(0)的话,就会一直wait,直到被notify。
调用这个方法的前提是当前线程必须持有这个对象的minotor。


protected void finalize() throws Throwable { }

当这个对象不再被引用时由垃圾回收器调用,子类覆盖这个方法用于释放系统资源。
在第一次垃圾回收发现不可达时,会先把finalize方法加到F-Q队列中由专门的线程执行,可以在这个方法中自救。如果没有自救或者自救失败,这个类就会被标记为可回收的,再下次垃圾回收时如果还是不可达,并且finalize执行过之后,就会真正的回收。
如果finalize方法发生异常,那么方法会终止,但是异常会被忽略。


public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }
    public final native Class<?> getClass();
    public native int hashCode();
    
    public boolean equals(Object obj) {
        return (this == obj);
    }
    
    protected native Object clone() throws CloneNotSupportedException;

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    public final native void notify();
    public final native void notifyAll();
    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);
    }
    protected void finalize() throws Throwable { }

猜你喜欢

转载自blog.csdn.net/ljz2016/article/details/83545257