java源码阅读--object

本文深入解析Java中的核心方法,如equals(), getClass(), clone(), toString(), notify(), notifyAll(), wait(), finalize()等,揭示它们的工作原理及与==的区别,探讨如何正确重写equals和toString方法,以及clone方法的实现细节。

native

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

首先看到这个方法不明白native修饰的方法是什么意思,谷歌后得到答案如下(同理Object里面的方法也是一样):

registerNatives函数前面有native关键字修饰,Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。方法的具体实现体在dll文件中,对于不同平台,其具体实现应该有所不同。用native修饰,即表示操作系统,需要提供此方法,Java本身需要使用。具体到registerNatives()方法本身,其主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。
既然如此,可能有人会问,registerNatives()修饰符为private,且并没有执行,作用何以达到?其实,在Java源码中,此方法的声明后有紧接着一段静态代码块:

   static {
        registerNatives();
    }

getClass();

调用本地方法返回运行时的类,所以关于类的元数据和方法信息可以通过它获得。

equals

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

Object类equals方法内部是用==进行比较,只判断对象的地址是否相等,不判断内容相等。所以我们判断一个对象的内容是否相等是要重写equals方法的(ps:一般内部方法都是重写过equals,只有我们自己写的类要比较对象内容是否相等的时候才要重写equals)

equals的作用及与==的区别(https://blog.youkuaiyun.com/u013063153/article/details/78808923)

equals被用来判断两个对象是否相等。
equals通常用来比较两个对象的内容是否相等,用来比较两个对象的地址是否相等。
equals方法默认等同于“

Object类中的equals方法定义为判断两个对象的地址是否相等(可以理解成是否是同一个对象),地址相等则认为是对象相等。这也就意味着,我们新建的所有类如果没有复写equals方法,那么判断两个对象是否相等时就等同于“”,也就是两个对象的地址是否相等。
但在我们的实际开发中,通常会认为两个对象的内容相等时,则两个对象相等,equals返回true。对象内容不同,则返回false。
所以可以总结为两种情况
1、类未复写equals方法,则使用equals方法比较两个对象时,相当于
比较,即两个对象的地址是否相等。地址相等,返回true,地址不相等,返回false。
2、类复写equals方法,比较两个对象时,则走复写之后的判断方式。通常,我们会将equals复写成:当两个对象内容相同时,则equals返回true,内容不同时,返回false。

clone方法(https://juejin.im/post/5950f6366fb9a06bc60407e4)

由本地方法表知道clone方法对应的本地函数为JVM_Clone,clone方法主要实现对象的克隆功能,根据该对象生成一个相同的新对象(我们常见的类的对象的属性如果是原始类型则会克隆值,但如果是对象则会克隆对象的地址)。Java的类要实现克隆则需要实现Cloneable接口,if (!klass->is_cloneable())这里会校验是否有实现该接口。然后判断是否是数组分两种情况分配内存空间,新对象为new_obj,接着对new_obj进行copy及C++层数据结构的设置。最后再转成jobject类型方便转成Java层的Object类型。

总结:我们常见的类的对象的属性如果是原始类型则会克隆值,但如果是对象则会克隆对象的地址

toString方法

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

逻辑是获取该类的名称+@+十六进制的hashCode值,一般自己写的类要重写toString方法

notify方法

此方法用来唤醒线程,final修饰说明不可重写。与之对应的本地方法为JVM_MonitorNotify,ObjectSynchronizer::notify最终会调用ObjectMonitor::notify(TRAPS),这个过程是ObjectSynchronizer会尝试当前线程获取free ObjectMonitor对象,不成功则尝试从全局中获取。

notifyAll方法

与notify方法类似,只是在取_WaitSet队列时不是取第一个而是取所有

wait方法

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

(第二个方法timeout++=timeout+nanos有点没弄清楚怎么搞得,哪位大佬解释一波,感谢!)

wait方法是让线程等待,它对应的本地方法是JVM_MonitorWait,间接调用了ObjectSynchronizer::wait,与notify对应,它也是对应调用ObjectMonitor对象的wait方法。该方法较长,这里不贴出来了,大概就是创建一个ObjectWaiter对象,接着获取_WaitSet队列锁将ObjectWaiter对象添加到该队列中,再释放队列锁。另外,它还会释放synchronized对应的锁,所以锁没有等到synchronized同步块结束时才释放。

finalize方法

这个方法用于当对象被回收时调用,这个由JVM支持,Object的finalize方法默认是什么都没有做,如果子类需要在对象被回收时执行一些逻辑处理,则可以重写finalize方法。

感谢:
作者:超人汪小建
链接:https://juejin.im/post/5950f6366fb9a06bc60407e4
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值