Object类是java中所有类的最终祖先,即java中每个类都是由它扩展而来。

Object作为父类,并不需要显式声明:class Employee extends Object。 因为编辑器会默认加上。

Object这个父类存在的意义,大概是给所有的类添加几个默认的方法。

一、equals方法

public boolean equals(Object obj) {
        return (this == obj);
    }

Object类中的equals方法用于检测一个对象是否等于另外一个对象。即两个对象是否具有相同的地址。

《java核心技术 卷1》中有关重写equals方法的建议:

1)显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量

2)检测this与otherObject 是否引用同一个对象

if(this == otherObject) return true;

这条语句是一个优化。因为计算这个等式要比一个一个地比较类中的域所付出的代价小得多

3)检测otherObject是否为null,如果为null,返回false

if(otherObject == null) return false;

4)比较this 与 otherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测

if (getClass() != otherObject.getClass()) return false;

如果所有的子类都拥有统一的语义,就使用instanceof检测

if (!(otherObject instanceof ClassName)) return false;

5)将otherObject转换为相应的类类型变量

ClassName other = (ClassName) otherObject

6)现在开始对所有需要比较的域进行比较了。

使用 == 比较基本类型域,使用equals比较对象域(如String)。如果所有的域都匹配,就返回true;反之,false

return field1 == other.field1 && field2.equals(other.field2) && ... ;

如果在子类中重新定义equals,就要在其中包含调用super.equals(other)

例如:

class Employee{
    public boolean equals(Object otherObject){
        if(this == otherObject) return true;
        if(otherObject == null) return false;
        if(getClass() != otherObject.getClass())
            return false;
        Employee other = (Employee) otherObject;
        return name.equals(other.name)
            && salary == other.salary
            && hireDay.equals(other.hireDay);
    }
}

在子类中定义equals方法时,首先调用超类的equals。如果检测失败,对象就不可能相等。如果超类中的域都相等,就需要比较子类中的实例域。

class Manager extends Employee{
    public boolean equals(Object otherObject){
        if(!(super.equals(otherObject))) return false;
        Manager other = (Manager) otherObject;
        return bonus == other.bonus;
    }
}

二、getClass方法

public final native Class<?> getClass();

这个方法能够返回某个对象在运行时的类型,即将这个对象实例化时使用的类

public class Test {
    public static void main(String[] args) {
        Person p = new Person(1,"刘德华");
        System.out.println(p.getClass());  //返回Class类型的对象
        System.out.println(p.getClass().getName()); // 获取类的名称
    }
}

class Person{
    int id;
    String name;
    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
}

注:特别的,当一个类是匿名内部类的时候,因为它并没有一个对应的有名字的类,所以在求一个匿名内部类的 Class 类型的时候,得到的是一个代号形式的类,其类名只是系统自动生成的一个编号类。

一般情况下使用这个方法的时候有两种:

1.在程序运行的过程中,我们可以通过获取两个对象的类型从而判断某两个对象是否是同一个类

2.是为了反射。

反射是 Java 提供的一种功能,通过反射,我们可以无视 Java 的一些限制访问机制,直接使用某个类的私有变量或私有方法。而进行反射的一般步骤就是,首先通过对象得到它所对应的类型,然后通过 Class 类提供的一些方法得到对应的变量或者方法,然后再通过这些 Field 类和 Method 类直接访问某个对象的某个变量或者方法,而不是通过一般的通过 . 操作符。反射相比较于一般情况下通过.操作符的调用机制来说,它一方面能够在运行时更加自由地操控对象的属性,另一方面,它能够无视 Java 的封装机制使用到一些在正常情况下无法使用的功能。

三、hashCode方法

public native int hashCode();

返回对象的散列码。散列码可以是任意的整数。

1、hashCode相等,两个对象不一定相等,需要通过equals方法进一步判断;

2、hashCode不相等,两个对象一定不相等;

3、equals方法为true,则hashCode肯定一样;

4、equals方法为false,则hashCode不一定不一样;

四、toString方法

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

用于返回表示对象值的字符串。

例如:

public String toString(){
	return "Employee[name=" + name
        + ",salary=" + salary
        + ",hireDay=" + hireDay
        + "]" ;
}