Java知识点拾遗——Object类

寒假在家的时候已经开始着手准备找实习的一些内容了,但是没想到这一切来的这么的快,3月刚到,各大互联网的实习信息就已经涌来。想想之前看 Thinking in Java 还是近一年前的事,真的需要认真准备一下了。于是打算搞一个知识点拾遗系列,把平时编程不太容易注意到的内容整理一下,也方便自己总结记忆。

Object 类是 Java 所有类的祖先,因此可以使用类型为Object的变量指向任意类型的对象。同时,因为 Java 类初始化顺序的原因,Object 类的默认构造方法 public object() 会在构造任何子类实例时调用。

因为Object 类是所有类的祖先,因此所有的类都拥有 Object 类的方法。Object 在 java 包中的位置是 java.lang.Object,所有 Java 程序都会默认导入这个包( TODO:默认导入哪些包?)。从下图可以看出来 Object 类拥有的所有方法。屏幕快照 2016-03-18 下午8.26.56

其中 registerNatives()这个方法 的介绍资料还没有看,不过看介绍似乎是和 JNI 相关的。

从图中还可以看出各个方法的修饰词:

  1. 红色代表 private,黄色代表 protected,绿色代表 public
  2. N 代表 native ,F 代表 final ,S 代表 static

其方法的含义:
clone()     创建并返回此对象的一个副本。
equals(Object obj)     指示某个其他对象是否与此对象“相等”。
finalize()     当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
getClass()     返回一个对象的运行时类。
hashCode()     返回该对象的哈希码值。
notify()     唤醒在此对象监视器上等待的单个线程。
notifyAll()     唤醒在此对象监视器上等待的所有线程。
toString()     返回该对象的字符串表示。
wait()     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
wait(long timeout)     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
wait(long timeout, int nanos)     导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

其中 hashCode 和 equals 两个方法都有仔细看过,前者主要用在 HashMap 等 Hash 相关的结构中作为键存储,equals 对比两个对象内容是否相同(和==对比),都应当在子类中重写。

getClass 应该是泛型相关的内容。wait 和 notify 应该是多线程相关内容。toString 则是对象的字符串表示,进行 print(对象) 时会自动调用。finalize 则是和垃圾回收相关的内容。这部分内容每部分都还需要查资料了解。下文还有待整理

1、equals():用于测试某个对象是否同另一个对象相等。它在Object类中的实现是判断两个对象是否指向同一块内存区域。其要求:自反性、传递性、对称性、一致性、非空性。Object 类的equals 方法直接使用对象的地址进行判定。子类在重写这个方法时,应当同时重写 hashCode 方法。

2、hashCode():一个对象的哈希值,在 HashMap 等结构中利用此函数的返回值作为键值。要求:在 Java 执行期间,同一对象上多次调用返回相同,前提是对象是 equals 的。equals 的对象其 hashCode 应当是相同的,hashCode 相同并不一定 equals。

3、getClass():返回一个对象的运行时类。该 Class 对象是由所表示类的 static synchronized 方法锁定的对象。返回表示该对象的运行时类的 java.lang.Class 对象。此结果属于类型 Class<? extends X>,其中 X 表示擦除表达式中的静态类型。(TODO:泛型相关)

4、clone():创建并返回此对象的一个副本。通常:

 

按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()

按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。

Object 类的 clone 方法执行特定的克隆操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出CloneNotSupportedException。注意:所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。

在没有实现 Cloneable 接口的对象上调用 clone(),会抛出 CloneNotSupportedException,其重写clone() 方法的子类上也会抛出此异常。

5、toString():返回该对象的字符串表示。通常,toString方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂。Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:

6、finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。Object 类的 finalize 方法执行非特殊性操作;它仅执行一些常规返回。

finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。

Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用 finalize 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对象的终结操作将终止。

在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。

对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。

finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它。

7、wait 和 notify、notifyAll:wait 函数导致当前的线程等待,直到其他线程调用此对象的 notify 方法或 notifyAll 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

notify 唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。notifyAll 唤醒所有线程,

当前的线程必须拥有此对象监视器。

此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,线程 T 被禁用,且处于休眠状态,直到发生以下四种情况之一:

  • 其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
  • 其他某个线程调用此对象的 notifyAll 方法。
  • 其他某个线程中断线程 T
  • 已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,该线程将一直等待,直到获得通知。

然后,从对象的等待集中删除线程 T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被还原到以前的状态 – 这就是调用wait 方法时的情况。然后,线程 Twait 方法的调用中返回。所以,从 wait 方法返回时,该对象和线程 T 的同步状态与调用 wait 方法时的情况完全相同。

 

直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:

  • 通过执行此对象的同步 (Sychronized) 实例方法。
  • 通过执行在此对象上进行同步的 synchronized 语句的正文。
  • 对于 Class 类型的对象,可以通过执行该类的同步静态方法。

一次只能有一个线程拥有对象的监视器。

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注