JAVA更多的類謎題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。如果你重載了一個方法,那么一定要確保所有的重載版本行為一致。