Object类是所有类的祖先类,如果一个类没有明确的父类,则它的父类就是Object类。Object类中以下几个比较重要的方法:
1. equals方法
public boolean equals(Object object)
该方法用来判断两个对象是否相等,Object类的默认实现是判断两个引用是否指向同一个对象,String类的实现则是判断两个字符串的内容是否相同。
我们通常应该在自己的类中覆盖该方法,覆盖该方法时常见的一个错误是:
public boolean equals(MyClass myClass)
这并不符合覆盖的定义,这实际上是和从Object类中继承来的equals方法构成重载。
Java语言规范对equals方法的实现提出如下要求:
(1)自反性 ,即x.equals(x)一定返回true
(2)对称性,即x.equals(y)为true ↔ y.equals(x)为true
(3)传递性,即x.equals(y)为true,且y.equals(z)为true,则x.equals(z)也为true
(4)x.equals(null)为false
在编写父类的equals方法时需要考虑的一点是:子类是否拥有自己决定是否相等的标准?
如果子类有自己的标准,则在父类中应该使用getClass()来检测传进来的参数是否是子类对象,是则返回false,要确保比较的两个对象都是父类类型;
如果由父类来决定判断所有子类的对象是否相等的标准,则在父类中可以使用instanceof来检测传进来的参数是否属于父类类型或者继承自父类。
下面给出一个比较好的equals方法编写模板:
class MyClass
{
public boolean equals(Object object)
{
if(object == null) return false;
if(object == this) return true;
//子类有自己决定是否相等的标准
if(getClass() != object.getClass()) return false;
//所有子类和父类决定是否相等的标准是一致的
// if( !( object instanceof MyClass ) ) return false;
MyClass obj = (MyClass)object;
//开始比较所有需要比较的域
// ........
}
}
上面的模板中如果MyClass还有父类(默认的Object类除外),则需要先调用super.equals方法判断父类中域是否相等,若不相等则没有必要再判断MyClass中的域是否相等。
2. hashCode方法
public int hashCode()
HashCode是由对象导出的一个整型数值,用来在哈希表结构中快速定位对象,Object类中的hashCode方法返回的是对象的地址。
我们要确保equals方法和hashCode方法的结果一致,如果x.equals(y)返回true,则一定有 x.hashCode() == y.hashCode() 。
3. clone方法
protected Object clone()
clone方法提供了拷贝一个对象的方法,Object类中默认的clone方法是protected的,这样在其他类中就无法直接使用。而且Object类中默认的实现是浅拷贝,即只拷贝基本类型的属性,而对于类对象的属性只拷贝引用,并没有拷贝对象的内容。因此,我们需要在子类中覆盖clone方法,并把访问权限改成public (即使默认实现满足要求,如果要使用clone方法,我们也需要将权限改成public)。
一个类要覆盖Object类中的clone方法,必须实现Cloneable接口。Cloneable接口是一个标记接口,并没有任何属性或者方法,Objec类并没有实现Cloneable接口,因此不能通过Object对象调用clone方法。
下面给出一个实现深拷贝的例子:
class People
{
private int age;
private String name;
public People clone() throws CloneNotSupportedException
{
//先调用父类的clone方法,这里即Object类的clone方法,拷贝了age
People people = (People)super.clone();
//name是String类型,Object类的clone方法没有拷贝内容
people.name = name.clone();
return people;
}
}
有人建议我们应该尽量避免使用clone方法,而是通过其他方法实现深拷贝(比如通过一系列的setter方法)。
参考资料 《Java核心技术》