谜题74 : 同一性的危机

下面的程序是不完整的,它缺乏对 Enigma 的声明,这个类扩展自 java.lang.Object。请为
Enigma 提供一个声明,它可以使该程序打印 false:

public class Conundrum {
public static void main(String[] args) {
Enigma e = new Enigma();
System.out.println(e.equals(e));
}
}

 

噢,还有一件事:你不能覆写 equals 方法。
乍一看,这似乎不可能实现。因为 Object.equals 方法将测试对象的同一性,通
过 Enigma 传递给 equals 方法的对象肯定是与其自身相同的。如果你不能覆写
Object.equals 方法,那么 main 方法必然打印 true,对吗?
别那么快下结论,伙计。尽管本谜题禁止你覆写(override)Object.equals 方
法,但是你是可以重载(overload)它的,这也就引出了下面的解谜方案:

final class Enigma {
// Don’t do this!
public Boolean equals(Enigma other){
return false;
}
}

 


尽管这个声明能够解决本谜题,但是它的做法确实非常不好的。它违反了谜题
58 的建议:如果同一个方法的两个重载版本都可以应用于某些参数,那么它们
应该具有相同的行为。在本例中,e.equals(e)和 e.equals((Object)e)将返回
不同的结果,其潜在的混乱是显而易见的。
然而,有一种解谜方案是不会违反这项建议的:

final class Enigma {
public Enigma() {
System.out.println(false);
System.exit(0);
}
}

  


可能会有些争论,这个解谜方案似乎违背了本谜题的精神:能够产生我们想要的
输出的 println 调用出现在了构造器中,而不是在 main 方法中。然而,它确实
解决了这个谜题,你不得不承认它很伶俐。
这里的教训,可以参阅前面的 8 个谜题和谜题 58。如果你重载了一个方法,那
么一定要确保所有的重载版本行为一致。

posted @ 2018-10-24 01:56  尐鱼儿  阅读(175)  评论(0编辑  收藏  举报