Object类及其方法
Object类是类层次结构的根类,Java所有类的超类,不能说是父类,因为Java是单继承的。
Object类的方法:
常用需要改写的的方法有toString,equals
toString()方法
toString方法会返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@
”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName() + '@' + Integer.toHexString(hashCode())
注意:一般新建对象建议改写,eclipse等工具可自动生成。
equals()方法
equals方法会返回类型boolean,equals
方法在非空对象引用上实现相等关系:
- 自反性:对于任何非空引用值
x
,x.equals(x)
都应返回true
。 - 对称性:对于任何非空引用值
x
和y
,当且仅当y.equals(x)
返回true
时,x.equals(y)
才应返回true
。 - 传递性:对于任何非空引用值
x
、y
和z
,如果x.equals(y)
返回true
,并且y.equals(z)
返回true
,那么x.equals(z)
应返回true
。 - 一致性:对于任何非空引用值
x
和y
,多次调用 x.equals(y) 始终返回true
或始终返回false
,前提是对象上equals
比较中所用的信息没有被修改。 - 对于任何非空引用值
x
,x.equals(null)
都应返回false
。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
equals和==的区别(偷了张图):
==代表同对象,equals需要看具体实现,下面是String的equals方法。
/** equals of String:same object or same length&char[]
public boolean equals(Object arg0) {
if (this == arg0) {
return true;
} else {
if (arg0 instanceof String) {
String arg1 = (String) arg0;
int arg2 = this.value.length;
if (arg2 == arg1.value.length) {
char[] arg3 = this.value;
char[] arg4 = arg1.value;
for (int arg5 = 0; arg2-- != 0; ++arg5) {
if (arg3[arg5] != arg4[arg5]) {
return false;
}
}
return true;
}
}
return false;
}
}
*/
String a1 = new String("abc"); String b1 = new String("abc"); System.out.println(a1==b1);//false System.out.println(a1.equals(b1));//true
hashCode()方法
hashCode方法返回int类型。返回该对象的哈希码值。
需要注意:如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode
方法都必须生成相同的整数结果。修改equals方法时,需修改hashcode方法保证,hashcode相同。
如果根据 equals(Object) 方法,afang两个对象是不相等的,那么对这两个对象中的每个对象调用 hashCode
方法不 要求一定生成不同的整数结果,但是,需要意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
getClass()方法
getClass()方法返回此 Object
的运行时类。返回的 Class
对象是由所表示类的 static synchronized
方法锁定的对象。返回的是一个class对象,后面可以跟class类的方法。用的是谁的构造函数,那么getClass返回的就是谁的类型,常用于反射。
clone()方法
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
需要注意:所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅度克隆”,而不“深度克隆”操作。关于深度克隆与浅度克隆我到了张图。
具体区别就是:当调用clone方法,object内存上未完全克隆,有公共部分,下图中Object实现接口Cloneable就会从浅度克隆到深度克隆。
finalize()方法
虚拟机gc清除对象的原则是从gc roots节点到对象是否可达(引用链),不可达后判断是否有必要执行finalize
方法,当gc确定不存在对该对象的更多引用时,且没必要执行finalize 方法后,就会清楚对象。
一般,子类重写 finalize
方法(未重写判定是没必要执行),目的是配置系统资源或执行其他清除。但是finalize不是C语言析构函数,是java诞生之初对C语言的内存管理妥协方案,运行代价高,不确定性大,无法保证各个对象的调用顺序,这方面try-finally处理的更好,所以常用try-finally配置系统资源或执行其他清除。
对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。
wait()、wait(long)、wait(long,int)、notify()、notifyAll()
这几个函数体现的是Java的多线程机制,在使用的时候要求在synchronize语句中使用
wait()
在其他线程调用此对象的 notify()
方法或 notifyAll()
方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify
方法,或 notifyAll
方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。wait(long) 和wait(long,int)用于设定下一次获取锁的距离当前释放锁的时间间隔。
IllegalArgumentException - 如果超时值是负数,或者毫微秒值不在 0-999999 范围内。
IllegalMonitorStateException
- 如果当前线程不是此对象监视器的所有者。
InterruptedException
- 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。
notify()
唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait
方法,在对象的监视器上等待。
notifyAll()
唤醒在此对象监视器上等待的所有线程。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争