JAVA更多的類謎題74:同一性的危機(jī)

字號(hào):

下面的程序是不完整的,它缺乏對(duì)Enigma的聲明,這個(gè)類擴(kuò)展自java.lang.Object。請(qǐng)為Enigma提供一個(gè)聲明,它可以使該程序打印false:
    public class Conundrum {
     public static void main(String[] args) {
     Enigma e = new Enigma();
     System.out.println(e.equals(e));
     }
    }
    噢,還有一件事:你不能覆寫equals方法。
    乍一看,這似乎不可能實(shí)現(xiàn)。因?yàn)镺bject.equals方法將測(cè)試對(duì)象的同一性,通過(guò)Enigma傳遞給equals方法的對(duì)象肯定是與其自身相同的。如果你不能覆寫Object.equals方法,那么main方法必然打印true,對(duì)嗎?
    別那么快下結(jié)論,伙計(jì)。盡管本謎題禁止你覆寫(override)Object.equals方法,但是你是可以重載(overload)它的,這也就引出了下面的解謎方案:
    final class Enigma {
     // Don’t do this!
     public Boolean equals(Enigma other){
     return false;
     }
    }
    盡管這個(gè)聲明能夠解決本謎題,但是它的做法確實(shí)非常不好的。它違反了謎題58的建議:如果同一個(gè)方法的兩個(gè)重載版本都可以應(yīng)用于某些參數(shù),那么它們應(yīng)該具有相同的行為。在本例中,e.equals(e)和e.equals((Object)e)將返回不同的結(jié)果,其潛在的混亂是顯而易見(jiàn)的。
    然而,有一種解謎方案是不會(huì)違反這項(xiàng)建議的:
    final class Enigma {
     public Enigma() {
     System.out.println(false);
     System.exit(0);
     }
    }
    可能會(huì)有些爭(zhēng)論,這個(gè)解謎方案似乎違背了本謎題的精神:能夠產(chǎn)生我們想要的輸出的println調(diào)用出現(xiàn)在了構(gòu)造器中,而不是在main方法中。然而,它確實(shí)解決了這個(gè)謎題,你不得不承認(rèn)它很伶俐。
    這里的教訓(xùn),可以參閱前面的8個(gè)謎題和謎題58。如果你重載了一個(gè)方法,那么一定要確保所有的重載版本行為一致。