提到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
- 对称性
对于任何非空引用值x
、y
,存在x.equals(y)
为true
时则y.equals(x)
也一定返回true
- 传递性
对于任何非空引用值x
、y
、z
,存在x.equals(y)
为true
,则y.equals(z)
也为true
,则x.equals(z)
也一定返回true
- 一致性
对于任何非空引用值x
、y
,不管多次调用x.equals(y)
,则始终返回true
或false
- 对于任何非空引用值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 (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)过后自动唤醒。