【源码解析】Java万象之源-Object

提到Java,那就不得不说Object类。在面试中,你也可能经常遇到Object类的问题,在这里总结一番,仅供大家参考。

Object类是Java中所有类的根类,即所有的类都继承了Object类。其包含的方法如下:

protected Object clone() throws CloneNotSupportedException

创建并返回对象的复制类。通常对于任何对象x,
- x.clone() != x返回为true
- x.clone().getClass() == x.getClass()返回为true
- x.clone().equals(x)返回为true

对象需要被clone,则需要实现Cloneable接口。Cloneable接口只是个标记,没有任何方法。

更深入的了解,对象克隆复制(包含深拷贝、浅拷贝等)请参考 https://www.cnblogs.com/Qian123/p/5710533.html

public boolean equals(Object obj)

判断两个对象是否为同一个对象。equals方法不能作用于null对象,具有以下特征:
- 自反性

对于任何非空引用值x,始终存在x.equals(x)true
- 对称性

对于任何非空引用值xy,存在x.equals(y)true时则y.equals(x)也一定返回true
- 传递性

对于任何非空引用值xyz,存在x.equals(y)true,则y.equals(z)也为true,则x.equals(z)也一定返回true
- 一致性

对于任何非空引用值xy,不管多次调用x.equals(y),则始终返回truefalse
- 对于任何非空引用值x,始终存在x.equals(null)false

重写equals()方法时,应同时重写hashCode()方法

面试中经常会问到“请谈谈Object中的==equals()方法的区别”:
其实,在Object类中这两者没有什么差别,均表示两对象所指向的内存地址是否相同。但是由于Java中存在着多态特性,子类可以重写equals()方法。譬如,String类中equals()表示两个字符串的值是否相同。

protected void finalize()

当GC(垃圾回收器)确定对象没有任何引用的时候,调用此方法。子类可以重写此方法来释放系统资源或进行其他的清理。

JVM虚拟机不能确定哪个线程来调用对象的finalize()方法,但是能确定的是调用finalize()方法的线程不会阻塞用户线程。如果执行方法时抛出异常,则对应对象的finalize()方法终止执行。另外,每个对象都只会执行一次finalize()方法。

public final Class<?> getClass()

返回此对象运行时的类。返回的类对象是由static锁方法锁住的对象。

int hashCode()

为对象返回哈希值。约定如下:
- 在程序相同执行过程中多次调用同个对象,哈希值必须返回相同。但不是相同调用过程则不必相同;
- 如果两个对象调用equals()方法相同,则hashCode()方法返回值必须相同;
- 如果两个对象调用equals()方法不相同,并不需要两个对象的哈希值不相同。但是编程的时候必须意识到,不同的对象产生不同的哈希值可以提高像HashTable这样类的性能。

void notify()

唤醒等待对象锁的某单个线程。如果有多个线程在等待,则随机唤醒其中一个,与其他要占用对象锁的线程之间竞争锁。

void notifyAll()

唤醒等待对象锁的所有线程。唤醒的线程与其他要占用对象锁的线程之间竞争锁。

String toString()

返回对象的String表示,默认是getClass().getName() + '@' + Integer.toHexString(hashCode())JDK规范要求:一般为了能清晰打印出对象属性,建议重写此方法。

笔者在通常项目中,都会写个Base类,重写toString方法,返回JSON字符串。让所有的自定义类都继承此Base类。

void wait()

占用对象锁的当前线程来调用,释放拥有的对象锁,直到其他线程调用notify()或者notifyAll()方法唤醒。

线程调用wait()方法时,可能存在假唤醒,所以此方法必须在循环中使用:

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

void wait(long timeout)

占用对象锁的当前线程来调用,释放拥有的对象锁,直到其他线程调用notify()或者notifyAll()方法唤醒或者指定时间过后自动唤醒。

void wait(long timeout, int nanos)

占用对象锁的当前线程来调用,释放拥有的对象锁,直到其他线程调用notify()或者notifyAll()方法唤醒或者指定时间(1000000*timeout + nanos)过后自动唤醒。

扩展阅读

  1. 【Effective Java】避免使用finalize方法
  2. 【Effective Java】覆盖equals时请遵守通用约定
  3. 【Effective Java】重写equals方法时必须重写hashCode 方法
  4. 【Effective Java】谨慎覆盖clone方法

猜你喜欢

转载自blog.csdn.net/xl890727/article/details/79921181