Object类源码分析
在Java的学习过程中,我们接触到最多的概念就是”对象“,对象作为面向对象编程的基础构成就好比细胞之于生物,砖头之于建筑。
在我们定义的所有对象中,他们有一个公共的父类就是Object类,Object类是对象的封装,对所有对象的一个抽象,定义了对象的一些基础行为,让JDK和我们自身程序进行派生。
首先先查看Object的源码信息
/*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
/**
* 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.
*
* @author unascribed
* @see java.lang.Class
* @since JDK1.0
*/
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
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);
}
protected void finalize() throws Throwable { }
}
下面对这些方法做一些说明
- registerNatives()
这是一个private static native void 方法,从修饰符可以看出这是一个与JNI相关的方法,比较底层,具体的方法实现一定在C/C++里面,下面是C中的事项,可以看出在Object类加载的时候会把hashCode()
,wait()
,notify()
,notifyAll()
,clone()
注册到对应的C方法上。
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));}
-
getClass()
getClass()方法在使用反射的情境下会用到,用来获取一个对象实例的类类型(字节码对象),Class<?>对象包含了类本身的一些信息包括字段,方法,修饰符,以及方法参数,注解等元数据。只要能过拿到Class<?>对象,我们就相当于获取了对象实例的root权限。 -
hashCode()
hashCode()方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个int数值,这个数值称作为散列值
This method is supported for the benefit of hash tables such as those provided byjava.util.HashMap
翻译一下就是这个方法使 hash表的数据存储结构受益比如HashMap.总的来说还是要配合与散列相关的数据结构使用HashMap,HashTable,HashSet等。当往这些集合添加数据时会比较元素的hashCode(),如果hashCode()已经存在说明此元素已经存在集合当中了。 -
equals()
equals 方法主要判断两个对象的引用类型是否指向同一个对象,这个方法在部分的类中被重写,比如java.lang.String
#equals
方法,String的判断逻辑是逐个比较两个字符串中的字符是否相等,如果有一个不相等那么equals方法直接返回false。 -
clone()
此方法创建并返回当前对象的一个副本,是一个native方法,需要拷贝的对象必须实现java.lang.Cloneable
接口,否则会抛出CloneNotSupportedException
异常。注意clone()方法实际上实现的是一种“浅拷贝”,即基本数据类型的成员有一个完整独立的副本,而引用类型的成员没有独立的副本,引用类型的变量的指向和源对象的引用在堆空间是同一个对象。 -
toString()
此方法返回对象的字符串形式.默认格式如下源码所示 ‘类名称@散列值的16进制’。在不同的类中应该重写此方法。
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
-
notify()
native方法,此方法和线程间的通信有关,任意一个对象持有一个监视器Monitor。用于唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,那么只唤醒一个等待的线程。 -
notifyAll()
native方法,此方法同上,用于唤醒在此对象监视器上等待的所有线程,被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。 -
wait()
native方法,此方法和线程间通信有关,调用wait()的线程将进入同步阻塞队列,并在此对象的监视器上无期限等待。 -
wait(long timeout)
native方法,此方法同上,调用wait(long timeout)的线程将进入同步阻塞队列,并在timeout时间后自动被唤醒。期间对象监视器的notify(),notifyAll()方法也能唤醒线程。 -
finalize()
/**
* Called by the garbage collector on an object when garbage collection
* determines that there are no more references to the object.
* A subclass overrides the {@code finalize} method to dispose of
* system resources or to perform other cleanup.
*
*/
native方法,此方法一般由JVM垃圾回收器调用,当垃圾回收器检测到该对象以及没有被其他对象引用时回收。尽量不要在程序中调用finalize(),由JVM内部回收机制管理比较好。