java源码阅读--object
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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。