Object类是Java中所有类的基类。定义的任何类都会默认继承Object类。Object类中有一系列重要的方法。
1. getClass
1 | public final native Class<?> getClass(); |
返回该对象运行时类的Class对象。Class对象记录了类的信息,包括属性、方法。被 static synchronized
修饰的方法锁住的即为该对象。
2. hashCode
1 | public native int hashCode(); |
返回该对象的一个hash值,该方法支持着各类哈希表的实现,如 HashMap
。
Object对该方法的默认实现是将对象的内部地址转换为一个整形值。
该方法的重写约定包括:
- Java应用程序执行期间多次对同一个对象调用
hashCode
方法时,只要没有修改在对象equals
方法比较中使用的信息,该方法就必须一致地返回相同的整数。但不要求同一应用程序在不同的执行中返回相同的值。 - 若根据
equals(Object)
方法得到两个对象相等,则两个对象的hashCode
需要返回相同的值。 - 若根据
equals(Object)
方法得到两个对象不相等,并不要求两个对象的hashCode
一定要返回不同的值。但设计时最好降低二者hashCode
返回相同值的概率,这样可以提高哈希表的性能。
3. equals
1 | public boolean equals(Object obj) { |
返回某个对象是否和当前对象“相等”。该方法实现了一个非空对象引用的等级关系。即
- 自反性:对于任何非空引用
x
,x.equals(x)
始终为true - 对称性:对于任何非空引用
x
,x.equals(y)
和y.equals(x)
同真假 - 传递性:对于任何非空引用
x
,若x.equals(y)
和y.equals(z)
为true,则x.equals(z)
为true - 一致性:对于任何非空引用
x
,假设equals
方法中用到的信息不被修改,则对x.equals(y)
的多次调用应始终返回相同的值 - 对于任何非空引用
x
,x.equals(null)
应始终返回false
4. clone
1 | protected native Object clone() throws CloneNotSupportedException; |
返回当前对象的一个拷贝对象。若类未实现 Clonealbe
接口会抛出 CloneNotSupportedException
,否则返回当前对象的一个浅拷贝,即新建一个对象,并简单地将当前对象所有属性的值赋给新对象。此外,所有数组类型 T[]
默认实现了 Clonealbe
接口,无论 T
是基本类型还是引用类型。
5. toString
1 | public String toString() { |
返回当前对象的字符串表示。建议在所有子类中重写它。
6. notify
1 | public final native void notify(); |
唤醒等待该对象monitor的一个线程。若有多个线程在等待,则会选择其中一个。选择是任意的,由实现自行决定。
在当前线程释放该对象的monitor之前,被唤醒的线程将无法继续执行。
调用该方法的线程必须持有当前对象的monitor(🔒)
一个线程可以通过三种方式获取对象的monitor。
- 通过执行一个对象的由
synchronized
修饰的实例方法 - 通过执行被
synchronized
修饰的代码块,且synchronized
锁住的是当前对象 - 对于Class类对象,通过执行该类被
static synchronized
修饰的方法
一个对象的monitor在一个时刻只能被一个线程持有。
7. notifyAll
1 | public final native void notifyAll(); |
唤醒所有等待该对象monitor的线程。
调用该方法的线程必须持有当前对象的monitor(🔒)
8. wait
1 | public final native void wait(long timeoutMillis) throws InterruptedException; |
使当前对象所在的线程进入等待状态,直到其他线程调用该对象的 notify
或 notifyAll
方法,或等待指定的时间。
调用该方法的线程必须持有当前对象的monitor(🔒)。
该方法会使当前线程将自身加入对象的等待集,然后放弃此对象上的任何同步声明。在以下四种情况发生前,当前线程将保持休眠,不参与线程调度。
- 其他线程调用对象的
notify
方法且当前线程正好被选中唤醒 - 其他线程调用对象的
notifyAll
的方法 - 其他线程调用当前线程的
interrupt
方法 - 经过指定的等待时间。若指定时间为0,则表示等待无限长时间,只能被其他三种方法唤醒。
达到触发条件后,当前线程将从对象的等待集中移除,并重新参与线程调度以及和其他线程对该对象的竞争。
注意,当wait方法将当前线程放入该对象的等待集时,它只解锁该对象。在线程等待时,当前线程上可能被同步的任何其他对象将保持锁定。
9. finalize
1 | protected void finalize() throws Throwable { } |
当垃圾收集确定没有对对象的更多引用时,由垃圾收集器在对象上调用。子类可以重写finalize方法来释放系统资源或执行其他清理。
finalize
方法中可以采取任何措施,包括使该对象再次对其他线程可用。但通常情况下,finalize
方法的作用是在该对象被无法恢复地销毁前执行一些清除操作,例如释放一些非Java资源(打开的文件、数据库连接)或调用非Java方法时分配的内存(C的malloc)。由于GC的不确定性,finalize
的调用时机也是不确定的。即,从一个对象变得不可达,到其 finalize
方法被调用,这期间经历的时间不确定,因此不要过于依赖 finalize
来完成资源回收,很可能在 finalize
被调用前资源就已耗尽。最好的方法是当不再需要分配给对象的资源时,在业务代码中就进行释放操作。
Java不能保证由哪个线程来调用给定对象的 finalize
方法。但可以保证的是,在调用 finalize
时,调用线程将不持有任何用户可见的同步锁。如果 finalize
方法抛出未捕获的异常,则该异常将被忽略,并且该对象的终结将终止。
finalize
方法最多只会被调用一次。
Object对象的 finalize
方法不执行任何特殊操作,它只是正常返回。Object的子类可以重写该方法。