一、Object类概述
Object类是Java中所有类的始祖,在Java中的每个类都是由它扩展而来的。
可以使用Object类型的变量引用任何类型的对象,例如:
Object obj = new Employee();
在Java中,只有基本类型不是对象,例如数值、字符和布尔类型值都不是对象。
所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类。
二、Object类常用方法
2.1 equals方法
Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用。一般情况下,直接判断两个对象的引用是否相等并没有意义,因此在子类中要覆盖equals方法。例如对于Employee类,若两个对象的名字、薪水和雇佣日期都一样,则可以认为它们是相等的。
在子类中定义equals方法时,首先要调用超类的equals。如果检测失败,对象就不可能相等。如果超类中的域都相等,就需要比较子类中的子类域,例如:
public class Manager extends Employee {
...
@Override
public boolean equals(Object otherObject) { // 注意传入的otherObject必须是Object类,否则不形成覆盖
if (!super.equals(otherObject)) return false; // super.equals检查父类Employee方法中的域是否都相等
Manager other = (Manager) otherObject;
return bonus == other.bonus; // 由于这是Manager类内部的方法,因此虽然bonus是private域,但仍然可以通过other.bonus来访问
}
...
}
如何编写equals方法:
- 显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量
- 检测this域otherObject是否引用同一个对象:
if (this == otherObject) return true;
- 检测otherObject是否为null,如果为null,返回false:
if(otherObject == null) return false;
- 比较this与otherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测:
if (getClass() != otherObject.getClass()) return false;
如果所有的子类都拥有统一的语义,就使用instanceof检测:
if (!(otherObject instanceof ClassName)) return false;
- 将otherObject转换为相应的类类型变量:
ClassName other = (ClassName) otherObject;
- 对所有需要进行比较的域做比较。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true,否则返回false:
return field1 == other.field1
&& Objects.equals(field2, other.field2)
&& ...;
如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。
注意:对于数组类型的域,可以使用静态的Arrays.equals方法检测响应的数组元素是否相等。
2.2 hashCode方法
散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的,若x和y是两个不同的对象,x.hashCode()和y.hashCode()基本上不会相同。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。
equals与hashCode的定义必须一致:如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。但是反之不成立。例如在把对象放入散列表时,就有可能由于两对象的散列码相同而产生碰撞。
如果存在数组类型的域,可以使用静态的Arrays.hashCode方法计算一个散列码。
2.3 toString方法
该方法用于返回表示对象值的字符串。绝大多数的toString方法都遵循这样的格式:类的名字,随后是一对方括号括起来的域值。
只要对象与一个字符串通过操作符“+”连接起来,Java编译器就会自动地调用toString方法,以获得这个对象的字符串描述。
对于数组类型的域,可以使用静态的Arrays.toString方法来生成数组的字符串。