Object 类是 Java 中所有类的父类,在 Java 中每个类都是由 Object 类扩展来的。所以,Object 中的实例方法也是所有 Java 对象可以使用的。
public final native Class<?> getClass();
该方法用于获得运行时的类型。该方法返回的是此 Object 对象的类对象运行时类对象 Class。获取 Class 对象还可以使用 Object.class
或者 Class.forName()
进行获取
public native int hashCode();
该方法返回当前对象的哈希值,这个值是对象的物理地址,取值范围是 -2^31 ~ 2^31 - 1
,通常和 equals()
方法一起进行重写,确保相等的两个对象拥有相等的 hashCode
。Java 规范对 hashCode 有以下几点约束:
- 对同一对象多次调用
hashCode()
方法时,必须一致地返回相同的整数,前提是将对象进行equals()
比较时所用的信息没有被修改 - 如果两个对象
x.equals(y)
方法返回 true,则 x、y 这两个对象的hashCode()
必须相等 - 如果两个对象
x.equals(y)
方法返回 false,则 x、y 这两个对象的hashCode()
可以相等也可以不等。 但是,为不相等的对象生成不同整数结果可以提高哈希表的性能。 - 默认的
hashCode()
是将内存地址转换为的哈希值,重写过后就是自定义的计算方式。也可以通过System.identityHashCode(Object o)
来返回原本的hashCode()
。
public boolean equals(Object o)
该方法用来比较两个对象的内容是否相等,默认情况下是比较引用是否指向同一对象,除非被子类重写了。
1 | public boolean equals(Object obj) { |
通常在重写 equals()
方法时需要遵守以下几条约定:
- 自反性:即
x.equals(x)
返回 true,x 不为 null - 对称性:即
x.equals(y)
与y.equals(x)
的结果相同,x 与 y 不为 null - 传递性:即
x.equals(y)
结果为 true,y.equals(z)
结果为 true,则x.equals(z)
结果也必须为 true - 一致性:即
x.equals(y)
返回 true 或 false,在未更改equals()
方法使用的参数条件下,多次调用返回的结果也必须一致。x 与 y 不为 null - 如果 x 不为 null,
x.equals(null)
返回 false
protected native Object clone() throws CloneNotSupportedException;
此方法返回当前对象的一个副本。需要注意的是,Object 类中的 clone()
方法是浅拷贝。这是一个 protected
方法,提供给子类重写。但需要实现 Cloneable
接口,这是一个标记接口,如果没有实现,当调用 Object.clone()
方法,会抛出 CloneNotSupportedException
异常,如下:
1 | public class CloneTest implements Cloneable { |
public String toString()
返回该对象的字符串表示,默认的 toString()
方法,只是将当前类的全限定性类名 + @
+ 十六进制的 hashCode()
值。
public final void wait() throws InterruptedException
该方法还有两个重载的版本,分别是:
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;
这三个方法是用来线程间通信用的,作用是阻塞当前线程,等待其他线程调用 notify()
/ notifyAll()
方法将其唤醒。这三个方法都是被 final
修饰过的,不可以被子类重写。
调用 wait()
方法的一些注意事项:
wait()
方法只能在当前线程获取到对象的锁监视器之后才能调用,否则会抛出IllegalMonitorStateException
异常。- 调用
wait()
方法,线程会将锁监视器进行释放。而Thread.sleep()
,Thread.yield()
并不会释放锁。 wait()
方法会一直阻塞,直到其他线程调用当前对象的notify()
/notifyAll()
方法将其唤醒。而wait(long timeout)
是等待给定超时时间内(单位毫秒),如果还没有调用notify()
/nofiyAll()
会自动唤醒。wait(long timeout, int nanos)
如果第二个参数大于 0 并且小于 999999,则第一个参数 +1 作为超时时间。
public final native void notify();
随机唤醒之前在当前对象上调用 wait()
方法的一个线程。
public final native void notifyAll();
唤醒所有之前在当前对象上调用 wait()
方法的线程。为什么 wait()
/ notify()
方法要放到 Object 中呢?因为每个对象都可以成为锁监视器对象,所以放到 Object 中,所有对象就都可以使用了。
protected void finalize() throws Throwable { }
此方法是在垃圾回收之前,JVM 会调用此方法来清理资源。此方法可能会将对象重新置为可达状态,导致 JVM 无法进行垃圾回收。这个方法需要以下几点:
- 永远不要主动调用某个对象的
finalize()
方法,该方法由垃圾回收机制自己调用 finalize()
何时被调用,是否被调用具有不确定性- 当 JVM 执行可恢复对象的
finalize()
可能会将此对象重新变为可达状态 - 当 JVM 执行
finalize()
方法时出现异常,垃圾回收机制不会报告异常,程序继续执行