Object类的知识点总结
概述:
1. Object类是所有其他类的父类
2. Object类只有一个构造方法,这也是为什么所有子类在调用构造方法时都会默认先调用父类的无参构造方法
3. Object类没有成员变量
方法:
1. public int hashCode()
2. public final Class getClass()
3. public String toString()
4. public boolean equals(Object obj)
5. protected void finalize()
6. protected Object clone()
具体方法:
- public int hashCode():
返回此对象的哈希码值(散列码),支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
1. 一致性:在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2. 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 如果重写了equals()方法,一定也要重写hashCode()方法
3. 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
重写:
int result = c;
//根据每一个关键域的hashcode去生成
31 * i == ( i << 5 ) - i ;
result = 31 * field.hashCode + result ;
…
return result;
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
- public final Class getClass()
返回此 Object
的运行时类。
Class:类类型,用来描述该类型的类
String getName():返回该类的全限定名
注意事项:
a) 返回的是运行时类
b) 用final修饰,所有对象该方法的行为一致
返回的 Class
对象是由所表示类的 static synchronized
方法锁定的对象。实际结果类型是 Class<? extends |X|>,其中 |X| 表示清除表达式中的静态类型,该表达式调用 getClass。
- public String toString()
返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
Object中toString的默认实现是返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。
getClass().getName() + “@” + Integer.toHexString(hashCode())
默认实现不能很好的体现对象,所以推荐子类都重写toString()
重写方式:
1. 根据关键域去重写
2. 快捷键生成
- public boolean equals(Object obj)
指示其他某个对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:
默认实现:
return this == obj ;
针对不同的类:
实体类:不同对象代表不同实体,采用默认实现即可
值类:关键域相等,就认为两个对象相等,需要重写equals方法
1. 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
2. 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
3. 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
4. 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
5. 非空性:对于任何非空引用值 x,x.equals(null) 都应返回 false。
(Java语法没有强制要求严格遵循这些原则,但是违反可能会对程序造成灾难性的后果)
重写:
a) 子类没有新的要比较的属性,就用instanceof进行判断
Demo:
public boolean equals(Object obj) {
if(obj instanceof Demo) {
Demo demo = (Demo) obj ;
//用关键属性进行比较
}
return false;
}
里氏替换原则
b) 子类有新的要比较的属性,就用getClass()方法进行判断
Demo:
public boolean equals(Object obj) {
if(obj == null || obj.getClass() != getClass() {
return false ;
}
Demo demo = (Demo) obj;
//用关键属性进行比较
}
没有遵循里氏替换原则
c) 快捷键生成
“==“ 和 equals 的区别
==:
a) 如果比较的是基本数据类型,判断他们的值是否相等
b) 如果比较的是引用数据类型,判断他们是否是同一个对象
equals:
a) 不能比较基本数据类型
b) 比较引用数据类型,如果没有重写Object的equals(),默认判断是否是同一个对象
c) 如果重写了,一般是根据对象的值进行判断
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
- protected void finalize()
垃圾回收器回收该对象之前,会调用该方法
作用:可以释放系统资源
注意事项:
a) 如果直接调用,相当于普通方法的调用,并不会回收该对象
b) 释放系统资源最好不要放在该方法里面,推荐使用try…catch…finally
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
子类重写 finalize 方法,以配置系统资源或执行其他清除。
finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。
Object 类的 finalize 方法执行非特殊性操作;它仅执行一些常规返回。Object 的子类可以重写此定义。
Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用 finalize 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对象的终结操作将终止。
在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。
对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。
finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它
- protected Object clone()
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。
默认:浅拷贝
如何实现深拷贝:
a) 实现Cloneable接口
b) 调用super.clone(),完成基本数据类型的拷贝
c) 对所有的引用数据类型完成深拷贝(下一级也应该实现深拷贝)
这样做的目的是,对于任何对象 x,表达式:
x.clone() != x为 true,表达式:
x.clone().getClass() == x.getClass()也为 true,但这些并非必须要满足的要求。一般情况下:
x.clone().equals(x)为 true,但这并非必须要满足的要求。
按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。
按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。