JDK源码之Object

1、Object类简介

复制代码
  java中所有的类都会继承Object类,属于java.lang包。
  Object类提供的方法如下:其中registerNatives()、getClass()、hashCode()、clone()、notify()、notifyAll()、wait(long timeout)为native方法,后面挑几个重要的方法讲一下。

native 为java的一个关键字

JNI:Java Native Interface ,从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互,例如C或者C++代码。

2、源码

2.1、getClass方法

复制代码
public final native Class<?> getClass();

getClass()方法返回对象运行时类。

2.2、hashCode方法

复制代码
public native int hashCode();

hashCode()返回对象的hash值,为int类型。那么对象创建好之后何时计算hashCode值?计算出的hashCode的值存放在那里呢?那么我们来看一下一个java对象组成 。

对象由对象头(对象头包括Mark Word 和 Class Pointer类型指针)、实例数据、对齐填充部分组成,数组对象比较特殊,会多数组长度部分。对齐填充部分时为了保证对象的大小是8字节的整数倍。

对象头中Mark Word用于存储对象自身的一些数据,具体存储信息如下图所示,对象头的大小在不同的虚拟机上的大小有所差异,通常为32bit或者64bit。

对象的hashCode值是在对象使用时调用hashCode函数时计算,并不是对象创建时就计算好的。

2.3、equals方法

复制代码
public boolean equals(Object obj) {
        return (this == obj);
    }

由源码可以看出,在Object这个类中,equals()方法和==是相同的,比较的是两个对象的引用是否相同。

我们比较两个字符串是否相等时,需要比较字符串本身的内容是否相等,而不希望比较字符串的引用地址是否相同,所有String类重写了equals()方法,让我一起看看源码。

复制代码
    public boolean equals(Object anObject) {
        if (this == anObject) { //如果引用的地址相同,那么这两个字符串必然相同,直接返回true
            return true;
        }
        if (anObject instanceof String) {//判断对象是否为String类型
            String anotherString = (String)anObject;//强转为String对象
            int n = value.length;//获取对象长度
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) { //依次比较每个字符
                    if (v1[i] != v2[i]) 
                        return false; //有一个不相同则返回false
                    i++;
                }
                return true; //内容完全,返回true
            }
        }
        return false; //不是String对象直接返回false
    }

如果在程序开发中需要比较对象的属性值是否相同,应该重写Object的equals方法,否则会调用Object的equals方法,使用==比较两个对象引用地址是否相同。

2.4、clone方法

复制代码
protected native Object clone() throws CloneNotSupportedException;

该方法实现对象的浅拷贝,使用clone()方法时,记得捕获CloneNotSupportedException异常,或者在类上实现Cloneable接口但不抛出该异常(尽管这在实际操作中不常见)。此外,使用clone()方法时要小心,因为它可能会导致性能问题或者在复杂对象图中出现问题(比如循环引用)。在Java中,通常推荐使用构造器或拷贝构造函数来实现浅拷贝或深拷贝,特别是在处理复杂对象时。。

浅拷贝(Shallow Copy)指的是创建一个新的对象,然后将原始对象的数据(字段)复制到新对象中。如果原始对象的字段是值类型(如int、double等基本数据类型,或者它们的包装类如Integer、Double等),这些值会被复制到新对象中。如果原始对象的字段是引用类型(如对象、数组等),那么这些引用类型的字段不会被复制其内容,而是复制引用本身的地址。这意味着新的对象和原始对象将引用同一个内存地址。

深拷贝:不仅复制对象本身,还递归地复制对象内部引用的所有对象。这意味着原始对象和副本对象不会共享任何引用指向的对象。

2.5、finalize方法

复制代码
 protected void finalize() throws Throwable { }

当一个Java对象被垃圾回收器标记为不再使用时,垃圾回收器会调用对象的finalize()方法来清理这个对象。但是垃圾回收器并不保证会立马调用该方法,可能会在后面某个何时的时间再调用。