走了一段值得的弯路
?
class C { int i; String j; public C(int i, String j) {this.i = i; this.j = j;} // #1 public boolean equals(Object o) { if (null == o) return false; if (o instanceof C) { C c = (C) o; return this.i == c.i && this.j.equals(c.j); } return false; }/* // #2 public boolean equals(C o) { if (null == o) return false; return this.i == o.i && this.j.equals(o.j); } */}class Ce extends C { int a; public Ce(int i, String j, int a) { super(i, j); this.a = a; }/* // #3 public boolean equals(Object o) { if (null == o) return false; if (o instanceof Ce) { Ce c = (Ce) o; return this.i == c.i && this.j.equals(c.j) && this.a == c.a; } return false; } *//* // #4 public boolean equals(Ce o) { if (null == o) return false; return this.i == o.i && this.j.equals(o.j) && this.a = o.a; }*/}class Cn { int i; String j; public Cn(int i, String j) {this.i = i; this.j = j;}}public class Test { public static void main(String[] args) { C o1 = new C(1, "o1"); Ce o2 = new Ce(1, "o1", 2); Cn o3 = new Cn(1, "o1"); System.out.println(o1.equals(o2)); System.out.println(o2.equals(o1)); System.out.println(o1.equals(o3)); }}?代码#1是马士兵讲重写 equals() 方法时的例程,我当时想按代码#2的方法重写equals方法是否同样成立而且跟简洁呢?因为类型检查的任务推给传参去完成了,#2的方法并不是重写Object类的方法,而是重载,当要比较的对象是本类及其子类实例时会调用这个方法,如果不是则会调用Object类的equals方法(比较引用是否相同,更严苛),这在初步实验中是没有问题的。
但是,当子类照类似的写法 #4 “重写”equals的时候,错误就出现了,原因仍是在于它是重载而非重写。子类重写的意图是不能与父类对象equals,但是#4的写法会在要比较父类对象时“意外地”调用父类的equals方法从而返回true。只有#1和#3的写法才能符合要求。
这条弯路的教训是:看似笨拙的逻辑其实较少歧义,比较健壮,不要一味追求“精巧”的优美,毕竟在实际应用之前测出一个反例是十分困难的。