在Java中,所有的对象都隐含的继承了Object类,Object类是Java程序中所有类的父类,当您定义一个类时: public class Foo {
// 实现 } 这个程序码相当于: public class Foo extends Object {
// 实现 } Object类定义了几个方法,包括"protected"的clone()、finalize()两个方法,以及几个"public"方法,像是equals()、toString()、getClass()、hashCode()、notify()、notifyAll()等等的方法,这些方法您都可以加以覆盖(除了 getClass()、notify()、notifyAll()、wait()等方法之外,它们被声明为 "final",无法被子类继承,所以无法覆盖),以符合您所建立的类需求,我会在以后的适当主题中介绍这些方法的使用。 由于Object类是Java中所有类的父类,所以它可以指向任何的对象而不会发生任何错误,这是很有用,以后您会看到一些 Java程序中,有些对象可以加入一些衍生类对象,并可透过方法调用会直接传回Object对象,这些对象可以经由类型(接口)转换而指定给衍生类类 型引用。 下面这个程序中,您制作一个简单的 集合(Collection)类,并将一些自订类对象加入其中,这个程序示范了Object的一个应用:
public class Foo1 {
public class Foo2 {
public class SimpleCollection {
public class Test { 执行结果:
在程序中,SimpleCollection对象可以加入任何类型的对象至其中,而传回对象时,您只要透过类型(接口)转换,就可以操作类型(接口)上的方法。 Object的toString()方法默认会传回以下的字符串: getClass().getName() + '@' +
Integer.toHexString(hashCode()); getClass()方法是Object中定义的方法,它会传回对象于运行时的Class实例,而hashCode()传回该对象的hash code,toString()方法用来传回对象的描述,通常是个文字性的描述,Object的toString()方法默认在某些场合是有用的,例如对象的自我检视时,但在这边,您将之覆盖为文字模式下使用者看得懂的文字描述。 上面这个程序范例虽然简单,但您以后一定会常常看到类似的应用,例如视窗程序容器、Vector类等等。 Object默认的equals()本身是比较对象的内存引用,如果您要有必要比较两个对象的内含数据是否相同(例如当对象被储存至Set时)您必须实现equals()与hashCode()。 一个比较常被采用的方法是根据对象中包括的所有属性值来作比较,来看看下面的一个例子: public class Cat {
... public boolean equals(Object other) { if (this == other) return true; if (!(other instanceof Cat)) return false; final Cat cat = (Cat) other; if (!getName().equals(cat.getName())) return false; if (!getBirthday().equals(cat.getBirthday())) return false; return true; } public int hashCode() { int result; result = getName().hashCode(); result = 29 * result + getBirthday().hashCode(); return result; } } 这称之为by value equality,更严格的比对是根据商务键值(Business key)实现equals()与hashCode(),商务键是一个属性或多个属性的结合,挑选那些可以从不为null、很少改变且组合后具有唯一性的属性。 API中对于equals()的合约是必须具备反身性(Reflexive)、对称性(Symmetric)、传递性(Transitive)、一致性(Consistent)。
可以参考API文件中Object类的hashCode()之建议:
两个不同的对象,可以传回相同的hashCode()结果,这是合法甚至适当的,只是对象会被丢到同一个杂凑桶中。 至于clone()方法,它是有关于如何复制对象本身,您可以在当中定义您的复制方法,不过对象的复制要深入的话必须考虑很多细节,您可以从 这篇文章 开始稍微了解一下如何定义clone()方法。 |