JDK源码阅读(一) java.util.Object

一、类

1.1 类修饰符

A. Object是所有类的父类。

B. 包括数组在内的所有对象都实现了Object类中的方法。

 

1.2 类结构图

 

二、字段

1.1 字段列表

无。

 

三、方法

3.1 方法列表

注:如上图,共有12个方法。另外包含了一个静态代码块。 

        绿色打开的锁代表是public,  红色关闭的代表是private, 灰色的钥匙代表的protected。

3.2 方法修饰符


3.3 方法详解

3.3.0 [静态]代码块

如图: 就是简单的调用了一下registerNatives方法,初始化另外几个native的方法。

 

3.3.1 构造函数

默认的无参构造函数。

注: 如果构造函数内什么操作都没有,那么该方法会省略不写,如Object。如果有特殊处理,则会手动写出来,如ArrayList。

 

3.3.2 registerNatives()

A. 首先native修饰的方法表明该方法的实现不是在JDK中,而是在操作系统中由C/C++中实现,并被编译成了 .dll 文件,由java去调用。对于不同平台,其具体的实现应该有所不同。

B. 网上找了一下,该方法主要是针对该类中的几个本地方法如hashCode, getClass等进行注册,也就是初始化java方法映射到C的方法中。

 

3.3.3 getClass()

A. 返回此对象的运行时类。返回的类对象是由表示类的静态同步方法锁定的对象。

B. 实例.getClass()调用的返回结果和Class.class结果返回相同,如下例子:

 

3.3.4 hashCode()

A. 返回对象的哈希值,该方法支持像HashMap这类的哈希表的实现。

B. 每当JAVA应用程序执行过程中在同一对象上多次调用时,只要没有修改equals方法, 那么该方法必定返回相同的哈希码。

C. 从应用程序的一次执行到同一应用程序的另一次执行,这个哈希值不需要保持一致。

D. 如果俩个对象根据equals方法进行比较时二者相等,则这俩个对象调用hashCode方法获取的哈希码必定相同;  如果俩个对象根据equals方法进行比较二者不相等时,这俩个对象调用hashCode方法获取的哈希码也可能相同。此时,二者没有必然联系。但是,程序员应该知道,为不同的对象生成不同的整数结果可能会提高哈希表的性能。

E. 只要合理可行,类对象定义的hashcode方法就不会为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换成整数来实现的,但是这种实现技术不是Java编程语言所需要的。)

 

3.3.5 equals()

A. 表示其他对象是否“等于”这个对象。

B. 请注意,每当这个方法被覆盖时,通常都需要覆盖hashCode方法,以便维护hashCode方法的一般契约,该方法声明相等的对象必须具有相等的哈希值。

 

3.3.6 clone

A. 创建并返回此对象的副本。该方法执行的是“浅拷贝”,而不是“深拷贝”。该方法将创建该对象类的一个新实例,并使用该对象相应字段的内容初始化所有字段,就像通过赋值一样,这些字段的内容本身不是克隆的;

B. 按照惯例,该方法返回的克隆对象应该是独立的。为了实现这种独立,在返回之前,可能需要通过super.clone()方法改变一个或多个该对象的字段。通常,这意味着,如果要复制的对象内部引用了一些可变对象,那么复制后返回的对象,对这些可变对象的引用应该是指向这些可变对象的副本;

C. 如果一个类没有实现Cloneable接口,就会抛出CloneNotSupportedException异常;Object类本身没有实现Cloneable接口,所以调用clone方法的如果是Object类的话,会导致在运行时抛出异常; 所有数组类型都被认为已经实现了Cloneable接口,而且一个数组T[]调用该方法的返回类型是数组T[],其中,T是任意的引用或原始数据类型。

 

3.3.7 toString

A. 返回一个表示这个对象的字符串。该字符串组成为: 类全名 + @ +  对象的哈希值的未签名的十六进制 组成。

B. 如下图:

 

3.3.8 notify()

A. 激活正在等待此对象监视器的单个线程。如果有线程正在等待这个对象,那么会选择唤醒其中一个线程。选择是任意的,并由实施者自行决定。线程通过调用其中一个wait方法来等待对象的监视器;

B. 在当前线程放弃此对象上的锁之前,唤醒的线程将无法继续。唤醒线程将以通常的方式与任何其他可能在该对象上为同步而主动竞争的线程竞争;例如,唤醒线程在成为下一个锁定该对象的线程时不享有可靠的特权或劣势;

C. 此方法只能由该对象监视器的所有者线程调用。线程通过以下三种方式之一成为对象监视器的所有者: 

     c1. 通过执行该对象的同步实例方法;

     c2. 通过执行在对象上同步的synchronized语句体;

     c3. 对于Class类型的对象,通过执行该类的同步静态方法;

D. 一次只能有一个线程拥有对象的监视器;

 

3.3.9 notifyAll()

A. 唤醒正在等待此对象监视器的所有线程。线程通过调用其中一个wait方法在对象的监视器上等待;

B. 在当前线程放弃此对象上的锁之前,唤醒的线程将无法继续。唤醒的线程将以通常的方式与任何其他可能在该对象上为同步而主动竞争的线程竞争;例如,唤醒的线程在成为下一个锁定该对象的线程时不享有可靠的特权或劣势;

C. 此方法只能由该对象监视器的所有者线程调用。有关线程成为监视器所有者的方式的描述,请参阅notify方法;

 

3.3.10 wait(long timeout)

A. 使当前线程等待,直到另一个线程为此对象调用notify方法或notifyall方法,或者指定的时间已过;

B. 当前线程必须拥有此对象的监视器;

C. 此方法使当前线程将自身置于此对象的等待集中,然后放弃此对象上的所有同步声明。出于线程调度目的,线程将被禁用,并处于休眠状态,直到发生以下四种情况之一: 
      c1. 其他一些线程调用此对象的notify方法,而线程恰好被任意选择为要唤醒的线程;

      c2. 其他一些线程为此对象调用notifyall方法;

      c3. 其它一些线程interrupt方法终端当前线程;

      c4. 指定的实时时间已过,或多或少。但是,如果超时为零,则不考虑实时性,线程只需等待通知;

然后将线程从该对象的等待集中删除,并重新启用线程调度。然后,它以通常的方式与其他线程竞争在对象上同步的权利;一旦它获得了对象的控制权,它在对象上的所有同步声明都将恢复到当前状态。也就是说,在调用wait方法时的情况下。然后线程从wait方法的调用返回。因此,从wait方法返回时,对象和线程的同步状态与调用wait方法时的状态完全相同;

D. 线程也可以在不被通知、中断或超时的情况下唤醒,这就是所谓的假唤醒。虽然在实践中很少发生这种情况,但是应用程序必须通过测试导致线程被唤醒的条件来防范这种情况,并且如果条件不满足,继续等待。换句话说,等待应该总是以循环的形式出现;

E. 如果当前线程在等待前或等待时被任何线程中断,则会引发InterruptedException。在按照上述说明还原此对象的锁定状态之前,不会引发此异常;

F. 请注意,wait方法在将当前线程放入该对象的等待集时,只解锁该对象;当线程等待时,可以同步当前线程的任何其他对象都将保持锁定状态。

G. 此方法只能由该对象监视器的所有者线程调用。有关线程成为监视器所有者的方式的描述,请参阅notify方法。

 

 

3.3.11 wait(long timeout, int nanos)

A. 使当前线程等待,直到另一个线程为此对象调用notify方法或notifyall方法,或某个其他线程中断当前线程,或经过一定的实时时间;

B. 此方法类似于一个参数的wait方法,但它允许更好地控制在放弃之前等待通知的时间。以纳秒为单位的实时量表示为:1000000*timeout+nanos(纳秒)。在所有其他方面,此方法与一个参数的方法wait(long)执行相同的操作。特别地,wait(0,0)与wait(0)的含义相同;

C. 当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待直到出现以下两种情况之一:

     c1. 另一个线程通过调用notify或notifyall方法通知等待此对象监视器的线程唤醒;

     c2. 超时时间(由timeout毫秒加nanos纳秒参数指定)已过。

    然后线程等待,直到它可以重新获得监视器的所有权并继续执行;

D. 与单参数版本一样,中断和虚假唤醒是可能的,并且该方法应始终在循环中使用;

E. 此方法只能由该对象监视器的所有者线程调用。有关线程成为监视器所有者的方式的描述,请参阅notify方法;

 

3.3.12 public final void wait()

A. 使当前线程等待,直到另一个线程为此对象调用notify方法或notifyall方法。换句话说,这个方法的行为就好像它只是执行调用wait(0)方法;

B. 当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待直到另一个线程通过调用notify方法或notifyall方法通知等待此对象监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并继续执行。

C. 与单参数版本一样,中断和虚假唤醒是可能的,并且该方法应始终在循环中使用;

D. 此方法只能由该对象监视器的所有者线程调用。有关线程成为监视器所有者的方式的描述,请参阅notify方法;

 

3.3.13 finalize()

A. 当垃圾回收确定不再有对对象的引用时,由垃圾回收器对对象调用。子类重写Finalize方法以释放系统资源或执行其他清理;

B. 通常finalize方法约定:如果Java虚拟机已经确定不再有任何手段可以通过任何尚未死亡的线程访问该对象,则调用它,除非由于某个其他对象或类的终结所采取的操作,而该对象或类已准备好finalized。Finalize方法可以采取任何操作,包括使该对象再次可用于其他线程;但是,Finalize的通常目的是在不可撤销地丢弃该对象之前执行清理操作;

C. Object类对象的finalize方法执行任何特殊操作,它只是正常返回。Object的子类可能会覆盖此定义;

D. Java编程语言不能保证哪个线程将调用任何给定对象的finalize方法。但是,可以保证调用finalize的线程在调用finalize时不会持有任何用户可见的同步锁。如果Finalize方法引发未捕获的异常,则忽略该异常并终止该对象的Finalize;

E. 在已为对象调用finalize方法之后,不再采取进一步的动作,直到Java虚拟机再次确定不再有任何方法可以通过任何尚未被访问的线程访问该对象,包括其他对象或类准备完成的可能动作,此时物体可能被丢弃。

F. 对于任何给定的对象,Java虚拟机绝不会对其进行多次调用finalize方法;

G. Finalize方法引发的任何异常都会导致终止此对象的Finalize,但否则将被忽略。