在Java中有这样一个类,它是所有类的祖先,任何类都是其子孙类,它就是java.lang.Object,如果一个类没有显式地指明其父类,那么它的父类就是Object。如同我们称自己为炎黄子孙一样,所有的类都可以称为Object子孙,^_^。在java中除了基本型别(数字、字符、布尔值,primitive type)不是对象之外,其它的均为对象(class type)。那么,这个Object到底给我们留下了什么“遗产”呢?下面将从最基本的讲起:
1. public boolean equals(Object obj).
所有的类均可以按照自己的需要对equals方法进行覆盖,顾名思义,这个方法可用来比较两个对象是否“相等”,至于什么才叫“相等”,各个类可以根据自己的情况与需要自行定义。例如String,就是要求两个对象所代表的字符串值相等,而对于一个雇员类(Employee),则可能是要求姓名、年龄、工资等一样才算是“相等”。尽管不同的类有不同的规则,但是有一条规则却是公用的,它就是:如果两个对象是“一样”(identical)的,那么它们必然是“相等”(equals)的。那么什么才叫“一样”?如果a==b,我们就说a和b是“一样的”,即a和b指向(refer to)同一个对象。Object类中的equals方法实施的就是这一条比较原则,对任意非空的指引值a和b,当且仅当a和b指向同一个对象时才返回true。
打开JDK5.0的帮助文档,我们会看到equals方法必须满足一系列性质:
A.自反性,即对任意一个非空的指引值x,x.equals(x)永远返回true;
B.对称性,对任意非空的指引值x和y,当且仅当x.equals(y)返回true时y.equals(x)返回true;
C.传递性,当x.equals(y)返回true并且y.equals(z)返回true时,x.equals(z)也返回true;
D.一致性,对任何非空的指引值x和y,只要x和y所指向(refer to)的对象没有发生变化,那么x.equals(y)的结果也不会变化;
E.对任意非空的指引值x,x.equals(null)应该返回false。
如何才能打造一个“完美”的equals方法呢,下面时JavaCore给出的建议:
第一步:把显式参数声明为otherObject(这个看个人喜好,不一定非得叫otherObject,至于什么叫显式参数什么叫隐式参数我就不赘术了)
第二步:检查待比较得两个值是否指向同一个对象(identical),就是用==进行比较,这是一个比较偷懒的步骤,如果那两个东东都一样了,就不用再比了。
第三步:测试otherObject是否为null,如果是则返回false
第四步:用getClass()方法或者instance of关键字对otherObject进行测试,主要是看待比较的两个reference是否指向同一个class type或者otherObject是否指向隐式参数所属的类或子类
第五步:通过第四步的测试后,就可以进行强制类型转换了,把otherObject强制转换成与隐式参数相同的类型
第六步:根据自己的业务逻辑和需要定义什么时候才是equal,如对所有的域进行比较,如果全部相同就返回true,否则返回false
2. public int hashCode()
每个类都可以复写Object类中的hashCode方法,Object类中的hashCode方法就是简单
地将对象在内存中的地址转换成int返回。这样,如果一个类没有复写hashCode方法,那么它的hashCode方法就是简单地返回对象在内存中的地址。在JDK中,对hashCode也定义了一系列约束,其中有一条就是如果两个对象是“equal”的,那么它们的hashCode方法返回的整数值必须相同,但是如果两个对象是“unequal”,那么hashCode方法的返回值不一定必须不同。正因为这个约束,我们如果复写了equals()方法,一般也要复写hashCode方法。
3.public String toString()
toString方法是一个从字面上就容易理解的方法,它的功能是得到一个能够代表该对象的一个字符串,Object类中的toString方法就是得到这样的一个字符串:this.getClass().getName() + '@' + Integer.toHexString(hashCode()),各个类可以根据自己的实际情况对其进行改写,通常的格式是类名[field1=value1,field2=value2……fieldn=valuen]。Core上面说这个方法对于写日志非常有用,暂时还没试过:)。