Java类始祖-Object

Java类始祖-Object

综述

Object 的类结构

类对象是类层次结构的根。 Object是所有类的超类(父类)。 所有的对象,包括数组,都实现了这个类的方法。

Object 中一共有12个方法。其中registerNatives()是唯一个静态方法,由 Object 中的静态代码块调用。其他 11 个都是实例方法。11 个实例方法中,被 final 修饰的方法有 6 个,包括 getClass() 方法和 5 个线程操作相关方法。

下面我们分别来看看其中的每一个方法。我们会将线程相关的方法放到最后面。

getClass()

//返回运行时的 Class 对象,在反射中大量用到. 
public final native Class<?> getClass();

另外两种获取 Class 对象的方式分别是 Class.forName() 和 类名.class

hashCode()

//返回运行时的 Class 对象,在反射中大量用到. 
public final native Class<?> getClass();

对于 hashCode() 的 通用约定:

  • 两个对象由 equal()方法判定相等,则两个对象的 hashcode() 方法结果必须相等。

  • 两个对象,如果根据 equals()方法不相等,则hashcode() 方法并非必须不相等。应当尽可能让不同对象返回不同的 hashcode() 值(减少哈希碰撞),因为可以让提高散列表的性能。

  • 在同一次 Java 程序的执行中,如果一个对象 equals()方法中用到的信息没有被修改,该对象多次调用hashcode() 方法返回的值应当是相同的。还是回到了,equals()判定相等,则 hashcode() 必须相等。

equals()

//判断两个对象是否相等。
public boolean equals(Object obj) {
    return (this == obj);
}

通常情况下,建议重写 equals()方法时,同时重写 hashcode() 方法,以保证 hashcode() 约定

clone()

创建并返回此对象的一个副本。

克隆又会分深复制和浅复制。浅克隆只是简单的执行当前对象clone(),当对象中的成员变量包含引用类型时,隆对象就和原始对象共享了一部分信息,显然是有问题的。这个时候就需要深克隆,如果不想克隆的副本和原副本共享这个引用类型,就需要对非基本类型的成员变量进行特殊处理,为变量也进行一份克隆,最终保证两个对象完全独立,这就是深克隆

toString()

//一个类的文本表示,通常是为了更易于人类阅读,比如用在日志记录上。推荐所有的子类都重写此方法。
//默认是 该类的类名+‘@’+hashcode()的无符号十六进制表示形式
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

finalize()

当垃圾收集器准备回收一个对象时,会执行该类的finalize()方法。 “finalize()方法是对象逃脱死亡命运的最后一次机会”。“稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。” “任何一个对象的finalize()方法都只会被系统自动调用一次,如果对象面临下一次回收,它的finalize()方法不会被再次执行” “建议大家尽量避免使用它,因为它不是C/C++中的析构函数,而是Java刚诞生时为了使C/C++程序员更容易接受它所做出的一个妥协。它的运行代价高昂,不确定性大,无法保证各个对象的调用顺序。有些教材中描述它适合做“关闭外部资源”之类的工作,这完全是对这个方法用途的一种自我安慰。finalize()能做的所有工作,使用try-finally或者其他方式都可以做得更好、更及时,所以笔者建议大家完全可以忘掉Java语言中有这个方法的存在。”

摘录来自: 周志明. <<深入理解Java虚拟机:JVM高级特性与最佳实践>>

wait 系列

导致当前线程等待,直到另一个线程调用此对象的 notify()notifyAll()。换句话说,此方法的行为就像它只是执行调用一样wait(0)

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

当前线程在发生以下四种情况之一之前处于休眠状态

  • 一些其他线程调用notify此对象的方法,并且线程T恰好被任意选择为要被唤醒的线程。

  • 其他一些线程调用notifyAll此对象的方法。

  • 其他某个线程中断 线程牛逼。

  • 指定的实时数量已经或多或少地过去了。timeout但是,如果 为零,则不考虑实时,并且线程只是等待通知。

notify 和 notifyAll

notify 唤醒正在此对象监视器上等待的单个线程。如果任何线程正在等待此对象,则选择其中一个线程被唤醒。选择是任意的,由实施决定。线程通过调用其中一个wait方法等待对象的监视器。

notifyAll 唤醒等待此对象监视器的所有线程。线程通过调用其中一个wait方法等待对象的监视器 。

脑图

参考

Java8 Doc 

One thought on “Java类始祖-Object

发表评论

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