美文网首页
JDK源码(一):Object

JDK源码(一):Object

作者: Ethan_zyc | 来源:发表于2019-03-16 00:01 被阅读0次

有句话叫 授人予鱼,不如授人以渔。之前的自己就是在不停的学各种框架,这是我认为但鱼,而学会去读源码就是渔。之前工作中遇到有些网上不能解答的问题就只能看源码,慢慢分析,说实话,自己这块能力比较弱,有时候会花很多时间。所以,从这周开始,每周五晚上至少读一个类的源码,尽可能弄懂,一方面巩固基础,另一方面学习优秀的代码风格,当然还有就是为了提升自己看源码的能力和速度。

首先看一下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将指定的本地方法绑定到指定函数,比如这里将hashCodeclone本地方法绑定到JVM_IHashCodeJVM_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()

但今天刚好看到这么一条:

image

finalize执行过程可参考这篇


第一天看的比较糙,中间也一直在查阅资料,深深感受到自己基础的不扎实,以后多看。

相关文章

网友评论

      本文标题:JDK源码(一):Object

      本文链接:https://www.haomeiwen.com/subject/ytadmqtx.html