有句话叫 授人予鱼,不如授人以渔。之前的自己就是在不停的学各种框架,这是我认为但鱼,而学会去读源码就是渔。之前工作中遇到有些网上不能解答的问题就只能看源码,慢慢分析,说实话,自己这块能力比较弱,有时候会花很多时间。所以,从这周开始,每周五晚上至少读一个类的源码,尽可能弄懂,一方面巩固基础,另一方面学习优秀的代码风格,当然还有就是为了提升自己看源码的能力和速度。
首先看一下Object
类的介绍:
Class {@code Object} is the root of the class hierarchy.Every class has {@code Object} as a superclass. All objects,including arrays, implement the methods of this class.
大概意思就是:Object
类是所有类的祖先(父类),所有对象都实现了这个类的方法。
registerNatives
接下来看一下这个类的内部,第一个方法就把我整懵逼了:
private static native void registerNatives();
static {
registerNatives();
}
native 修饰符表示这个方法用到了非java代码去实现,比如用C或C++实现。native 本身翻译出来就是原生的嘛,java底层就是C/C++写的嘛。
关于 registerNatives()
我找到了这个回答。
被点赞最多的回答:有了这个方法,类似这个方法java.lang.Object.registerNatives
本来是需要被命名成这样Java_java_lang_Object_registerNatives
的,因为native方法需要按照C的命名规则来,但有了这个方法就不需要了。可以帮你一一去映射到相对应的方法名。
另一篇文章中也有相关解释:本地中通过registerNatives
将指定的本地方法绑定到指定函数,比如这里将hashCode
和clone
本地方法绑定到JVM_IHashCode
和JVM_IHashCode
函数。
getClass
public final native Class<?> getClass();
getClass()
方法返回运行时对象的字节码文件。
为什么是运行时,可以看这个例子:
static void foo(List l) {
System.out.println(l.getClass().getName());
}
foo(new LinkedList()); // Outputs "java.util.LinkedList"
foo(new ArrayList()); // Outputs "java.util.ArrayList"
并且该返回的Class对象是被静态同步方法锁定的对象。
hashCode
public native int hashCode();
hashCode方法前面有个native的修饰符,也就表示hashCode方法是由非java语言实现的,具体的方法实现在外部,返回内存对象的地址。
在java的很多类中都会重写equals和hashCode方法。最常见的String类,比如定义两个字符相同的字符串,那么对它们进行比较时,我想要的结果应该是相等的,如果你不重写equals和hashCode方法,他们肯定是不会相等的,因为两个对象的内存地址不一样。
如果两个对象相等,那么它们的hashCode()值一定相同。但反过来则不然。举个例子:
System.out.println("Aa".hashCode()); // 2112
System.out.println("BB".hashCode()); // 2112
equals
public boolean equals(Object obj) {
return (this == obj);
}
this == obj
代表这两个对象的内存地址相同才返回true,一般都会重写equal方法。
clone
protected native Object clone() throws CloneNotSupportedException;
其实就是克隆字面意思,但我们还要深入研究下,这到底是深拷贝还是浅拷贝:
关于深浅拷贝:如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。
先定义一个这样的类:
Cloneable 是个标记接口,接口中没有任何方法去实现,实现这个接口表明这个类的对象可以被clone,否则会报CloneNotSupportedException
/**
* @author ethan
* @date 2019/3/15 22:43
*/
public class TestClone implements Cloneable {
private Integer intValue;
private String strValue;
public TestClone() {
}
public TestClone(Integer intValue, String strValue) {
this.intValue = intValue;
this.strValue = strValue;
}
@Override
protected TestClone clone() throws CloneNotSupportedException {
return (TestClone) super.clone();
}
public Integer getIntValue() {
return intValue;
}
public void setIntValue(Integer intValue) {
this.intValue = intValue;
}
public String getStrValue() {
return strValue;
}
public void setStrValue(String strValue) {
this.strValue = strValue;
}
}
TestClone origin = new TestClone(10, "abc");
TestClone clone = origin.clone();
System.out.println(origin == clone); // false
现在看clone应该是深拷贝,因为origin和clone不是同一个引用,我一开始也这么以为,但其实不然,我们接着往下看。
TestClone origin = new TestClone(10, "abc");
TestClone clone = origin.clone();
System.out.println(origin == clone); // false
System.out.println(origin.getStrValue() == clone.getStrValue()); // true
对象中的引用变量指向内存中同一个值,由此得出结论,clone是浅拷贝。
notify/notifyAll/wait
这几个我放一起了,其实最困惑我的是为什么这几个方法会出现在Object
类中?
参考这了两篇:How can the wait() and notify() methods be called on Objects that are not threads?
java-为什么wait,notify和notifyall定义在Object中
最简单的理由是:因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify();所以wait和notify属于Object。
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);
}
finalize
protected void finalize() throws Throwable { }
A subclass overrides the finalize method to dispose of system resources or to perform other cleanup.
垃圾回收器准备释放内存的时候,会先调用finalize()
但今天刚好看到这么一条:
imagefinalize
执行过程可参考这篇。
第一天看的比较糙,中间也一直在查阅资料,深深感受到自己基础的不扎实,以后多看。
网友评论