Java Object 方法简析

Java中,Object类提供了一下方法

public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj);
protected native Object clone() throws CloneNotSupportedException;
public String toString();
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;
public final void wait() throws InterruptedException;
protected void finalize() throws Throwable;

1. getClass

这是一个final且native方法,即不允许子类修改,且由非Java语言实现.
返回某个运行时对象的class<? extend |X|>.

 Number n = 0.0;
Class<? extends Number> nClass = n.getClass();
System.out.println(nClass.equals(Double.class)); //true

Number n2 = 0;
Class<? extends Number> n2Class = n.getClass();
System.out.println(nClass.equals(Integer.class)); //true

应该注意的是,返回的是运行时的类对象。举个例子,当你将一个Number对象初始化为小数的时候,Java默认它为double类型,此时你getClass获取到的class对象就是Double。当你将它初始化为整数的时候,Java默认它为Integer类型,此时你获取到的class即为Integer。

2. hashCode

该函数返回对象的哈希值,常用于哈希表中。这也是一个native方法。
该方法有着如下的约定:

  1. 在同一个Java程序的运行过程中,在对象不修改“equals”方法中所用信息的前提下,该对象返回的hashCode始终是相同的。同时,不同Java程序中对象的hashCode不保持相同。
  2. 若通过equals方法比较得到两个对象是相等的话,那么这两个对象的hashCode也必须是一致的。所以若重写了equals方法,hashCode方法一定要跟着重写。
  3. 不相等的对象不保证hashCode一定不相等。但为不相等的对象赋予不相等的hashCode可以提高hashTable的性能。
    Object类中定义的hashCode方法为不同的对象产生不同的hashCode,一般是通过将对象的内部地址换算成整数。不过Java中定义的各种类型一般会重写hashCode方法。比如Integer中返回的是该对象的value值:
@Override
public int hashCode() {
  return Integer.hashCode(value);
}
public static int hashCode(int value) {
  return value;
}

而在String中,缓存了hash值,节省了重复计算的开销。

public int hashCode() {
  int h = hash;
  if (h == 0 && value.length > 0) {
    char val[] = value;

    for (int i = 0; i < value.length; i++) {
        h = 31 * h + val[i];
     }
    hash = h;
  }
  return h;
}

3. equals

该方法用于判断两个对象是否相等。Object提供的默认方法中,通过判断两个对象的内存地址是否相等,也就是说调用X.equals(Y)的时候,会判断X、Y是否指向同一个对象。

public boolean equals(Object obj) {
    return (this == obj);
}

该方法的实现对于所有非null的对象,必须具备以下特性:

  1. 自反性,即X.equals(X)必须为true
  2. 对称性,即X.equals(Y)和Y.equals(X)的计算结果必须一致
  3. 传递性,即若X.equals(Y)=true且Y.equals(Z)=true,则X.equals(Z)必须为true
  4. 一致性,即当equals方法需要的信息没有被改变的情况下,无论执行多少次,X.equals(Y)的结果都必须是相同的
  5. 对于任何非null的对象,X.equals(null)结果必须为false

值得注意的是,一旦重写equals方法,则必须重写hashCode方法,确保相同的对象有相同的哈希码。这一点在hashCode方法介绍中也有提到。

4. clone

该方法创造并返回对象的一个拷贝。通常情况下,拷贝的定义满足以下约束,即对象的拷贝与原对象不是同一个对象,但与原对象数据和类型完全相同。类比一下,文件和文件的复印件内容和类型是一模一样的(忽略印刷错误等),但两者在物理意义上是两件物品。不过这个定义不是绝对的,一般根据需求和场景定义

x.clone() != x //true
x.clone().getClass() == x.getClass() //true
x.clone().equals(x) //true

有两点值得注意:

  1. Object没有实现Cloneable接口,所以调用Object类对象的clone方法的时候会抛出CloneNotSupportedException异常
  2. 数组默认的拷贝是“浅拷贝”操作。在Java中,所有数组被视为实现Cloneable接口,返回类型是T [],其中T是任何引用或基本类型。此方法会创建此对象的类的新实例,并使用该对象的相应字段的内容通过赋值初始化其所有字段,而这些字段的内容本身不会被克隆。

5. toString

该方法返回一个代表着该对象信息的字符串,这个字符串需要做到简洁易读懂。Object中默认返回“对象的类名@该对象哈希码的16进制表示”

public String toString() {
   return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

建议所有的Object子类都重写该方法,在调试或者记录log的时候非常有用。

6. notify

唤醒一个在此对象监视器上等待的线程,若有多个等待的线程,则随机唤醒其中某一个。
线程被唤醒后并不能马上进行处理,而是要等待当前线程释放对象锁之后才可以继续处理,同时被唤醒的线程还需要与其他在该对象同步的其他线程竞争锁。
一个线程若要成为对象监视器的所有者,有以下3种方法:

  1. 执行对象的同步实例方法
  2. 使用synchronized内置锁
  3. 对于Class类型的对象,执行同步静态方法
    值得注意的是,notify方法只能被作为此对象监视器所有者的线程调用,且一次只能有一个线程拥有对象的监视器。若当前线程不是此对象监视器所有者的话会抛出IllegalMonitorStateException异常

7. notifyAll

功能和注意点同notify方法,区别是该方法用于唤醒在此对象监视器上等待的所有线程。当所有线程被唤醒后,需要等待当前线程释放锁,并同其他线程竞争。

8. wait(long timeout)

让一个线程进入等待状态,直到被notify/notifyAll方法唤醒,或者过了规定的时间
这个方法会致使当前线程(简称T)被加入到等待集合中并释放其所拥有的资源和锁。出于线程调度的目的,线程T将不可用并进入休眠状态,直到发生以下四件事中的任意一件

  1. 其他某个线程调用此对象的notify方法,碰巧选中并唤醒了T
  2. 其他某个线程调用此对象的notifyAll方法
  3. 其他某个线程调用Thread.interrupt方法中断线程T
  4. 时间到了参数设置的超时时间。如果timeout参数为0,则不会超时,会一直进行等待,即wait(0)等同于wait()

值得注意的是,一个线程也可能在没有被唤醒、中断或超时的情况下醒过来,这种称之为“虚假唤醒”。虽然这种情况在实践中很少发生,但是应用程序有必要对应该导致该线程被唤醒的条件进行测试,若条件不满足,则继续等待。如下所示:

synchronized (obj) {
   while (<condition does not hold>)
        obj.wait(timeout);
         ... // Perform action appropriate to condition
}

9. wait(long timeout, int nanos)

这个方法的表现形式和wait(long timeout)是一致的,只不过超时时间计算方式如下:1000000*timeout+nanos,其中nanos表示额外的时间,单位为毫微秒。
于是,我们有wait(0,0)=wait(0)=wait(0)

10. wait

与其他两个wait方法的唯一不同,是该方法会让线程一直等待,知道被notify方法或notifyAll方法唤醒。
再次提醒,调用以上与线程等待和唤醒相关的方法(notify/notifyAll/wait)的时候,当前线程必须是此对象的监视器所有者,否则会抛IllegalMonitorStateException异常

11. finalize

该方法会在对象被垃圾回收机制回收之前调用,用于释放资源或执行其他清理。Object默认不做任何操作,子类可以根据自身需求重写。
Java不保证哪个线程将会调用任何给定对象的finalize方法。 但是保证在调用finalize时,调用该方法的线程不会持有任何用户可见的同步锁。 如果finalize方法抛出未捕获的异常,则会忽略该异常并结束该对象当前执行的finalize操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • Java中的Object类是所有类的父类,它提供了以下11个方法: public final native Cla...
    CHSmile阅读 479评论 0 0
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,062评论 0 62
  • 偶然的瞬间,你收到一个多年来未联系的小学同学的来电,被告知对方要结婚了。是的,你没听错,也不要惊讶,她要结婚了。你...
    谁还记得那年初夏阅读 324评论 0 2
  • 2017年七月!很痛苦的七月,那个说最爱我的人又一次背叛了我。那个说丫头哥会对你好以后会更好。在那个七月又一次背叛...
    丫头莫忘初心阅读 219评论 0 1