文章目录
Object 的重要性
学习 Java 的同学都知道,Object 是一个很重要的类,它是所有类的父类。在日常开发中我们可能经常要与 Object 打交道,如果还不熟悉 Object ,肯定是说不过去的。
我认为熟悉 Java 很难,熟悉 Object 却不难,单单一个 Object 尚且不敢言胜,我们又哪有勇气去深入剖析 Java 的内核呢?
Object 的源码
纸上谈兵终归是落了下乘,想要真正熟悉 Object ,我们还得从源码入手。
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
public class Object {
@HotSpotIntrinsicCandidate
public Object() {}
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
@HotSpotIntrinsicCandidate
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
@HotSpotIntrinsicCandidate
public final native void notify();
@HotSpotIntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
@Deprecated(since="9")
protected void finalize() throws Throwable { }
}
从源码中我们可见,Object 共有 11 个方法。而且大部分方法前面都带有 native 修饰符,这个修饰符表示本方法为本地方法,该方法的实现并不是 Java,而是 C/C++,而且方法的实现并不在本文件中。
为什么这部分的方法的实现要使用别的语言,而不能是 Java 呢?一方面,Object 的方法大部分与底层有关,且 Java 不能操作操作系统底层,但是可以通过 JNI 接口调用其他语言来实现对底层的访问,另外一个角度,使用本地方法可能在性能方面更有优势一点。
对 Object 各个方法的简介
getClass 方法
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
该方法是一个本地方法,由 final 修饰可知该方法不允许子类重写,它返回一个 Class 对象,该对象使用的是哪一个类的构造函数,返回的就是哪一个类的 Class 对象。该方法经常在反射机制中被用到。
hashCode 方法
@HotSpotIntrinsicCandidate
public native int hashCode();
该方法是一个本地方法,返回对象的哈希码。
equals 方法
public boolean equals(Object obj) {
return (this == obj);
}
一般用于比较两个对象是否相等,在未被子类重写的情况下 equals 用于比较两个对象的内存地址是否相等。
clone 方法
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
该方法是一个本地方法,用于创建并返回当前对象的一份拷贝。
toString 方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
该方法返回对象的字符串表示形式,其实实际上返回的是一个 “类名@哈希码” 的字符串。
notify 方法
@HotSpotIntrinsicCandidate
public final native void notify();
该方法是一个本地方法,由 final 修饰可知该方法不允许子类重写,作用为唤醒一个在此对象锁上等待的线程,如果有多个线程在等待则只会唤醒一个。
notifyAll 方法
@HotSpotIntrinsicCandidate
public final native void notifyAll();
该方法是一个本地方法,由 final 修饰可知该方法不允许子类重写,作用与 notify 相似,其区别为 notifyAll 会唤醒在此对象锁上等待的所有线程,而不仅仅是一个。
wait 方法
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
该方法是一个本地方法,由 final 修饰可知该方法不允许子类重写,一般与 notify/notifyAll 配套使用,作用为让当前正在执行的线程进入线程阻塞状态的等待状态,它只能在同步代码块或同步方法中调用,且执行后当前线程释放锁。
finalize 方法
@Deprecated(since="9")
protected void finalize() throws Throwable { }
finalize 方法与 Java 的垃圾回收机制有关,在垃圾回收器准备释放对象占用的存储空间时,会首先调用其 finalize 方法(每个对象的 finalize 方法只能被执行一次),如果它能够与引用链(GC-Roots)上的任何一个对象关联,就可以存活下来,否则将会被回收。