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核心技术》