Java庫(kù)謎題63:更多同樣的問(wèn)題

字號(hào):

下面的程序除了是面向?qū)ο蟮倪@一點(diǎn)之外,與前一個(gè)非常相似。因?yàn)閺那耙粋€(gè)程序中已經(jīng)吸取了教訓(xùn),這個(gè)程序使用了一個(gè)通用目的的Map實(shí)現(xiàn),即一個(gè)HashMap,來(lái)替代前一個(gè)程序的IdentityHashMap。那么,這個(gè)程序會(huì)打印出什么呢?
    import java.util.*;
    public class MoreNames {
     private Map m = new HashMap();
     public void MoreNames() {
     m.put("Mickey", "Mouse");
     m.put("Mickey", "Mantle");
     }
     public int size() {
     return m.size();
     }
     public static void main(String args[ ]) {
     MoreNames moreNames = new MoreNames();
     System.out.println(moreNames.size());
     }
    }
    這個(gè)程序看起來(lái)很直觀,其main方法通過(guò)調(diào)用無(wú)參數(shù)的構(gòu)造器創(chuàng)建了一個(gè)MoreNames實(shí)例。這個(gè)MoreNames實(shí)例包含一個(gè)私有的Map域(m),它被初始化成一個(gè)空的HashMap。該無(wú)參數(shù)的構(gòu)造器似乎將兩個(gè)映射關(guān)系放置到了映射表m中,這兩個(gè)映射關(guān)系都具有相同的鍵(Mickey)。我們從前一個(gè)謎題已知,棒球手(Mickey Mantle)應(yīng)該覆蓋嚙齒明星(Mickey Mouse),從而只留下一個(gè)映射關(guān)系。main方法之后在MoreNames實(shí)例上調(diào)用了size方法,它會(huì)調(diào)用映射表m上的size方法,并返回結(jié)果,我們假設(shè)其為1。這種分析還剩下一個(gè)問(wèn)題:該程序打印的是0而不是1。這種分析出了什么錯(cuò)呢?
    問(wèn)題在于MoreNames沒(méi)有任何程序員聲明的構(gòu)造器。它擁有的只是一個(gè)返回值為void的實(shí)例方法,即MoreNames,作者可能是想讓它作為構(gòu)造器的。遺憾的是,返回類型(void)的出現(xiàn)將想要的構(gòu)造器聲明變成了一個(gè)方法聲明,而且該方法永遠(yuǎn)都不會(huì)被調(diào)用。因?yàn)镸oreNames沒(méi)有任何程序員聲明的構(gòu)造器,所以編譯器會(huì)幫助(真的是在幫忙嗎?)生成一個(gè)公共的無(wú)參數(shù)構(gòu)造器,它除了初始化它所創(chuàng)建的域?qū)嵗?,不做任何事情。就像前面提到的,m被初始化成了一個(gè)空的HashMap。當(dāng)在這個(gè)HashMap上調(diào)用size方法時(shí),它將返回0,這正是該程序打印出來(lái)的內(nèi)容。
    訂正該程序很簡(jiǎn)單,只需將void返回類型從MoreNames聲明中移除即可,這將使它從一個(gè)實(shí)例方法聲明變成一個(gè)構(gòu)造器聲明。通過(guò)這種修改,該程序就可以打印出我們所期望的1。
    本謎題的教訓(xùn)是:不要因?yàn)榕既坏靥砑恿艘粋€(gè)返回類型,而將一個(gè)構(gòu)造器聲明變成了一個(gè)方法聲明。盡管一個(gè)方法的名字與聲明它的類的名字相同是合法的,但是你千萬(wàn)不要這么做。更一般地講,要遵守標(biāo)準(zhǔn)的命名習(xí)慣,它強(qiáng)制要求方法名必須以小寫字母開(kāi)頭,而類名應(yīng)該以大寫字母開(kāi)頭。
    對(duì)語(yǔ)言設(shè)計(jì)者來(lái)說(shuō),在沒(méi)有任何程序員聲明的構(gòu)造器的情況下,自動(dòng)生成一個(gè)缺省的構(gòu)造器這種做法并非是一個(gè)很好的主意。如果確實(shí)生成了這樣的構(gòu)造器,也許應(yīng)該讓它們是私有的。有好幾種其他的方法可以消除這個(gè)陷阱。一種方法是禁止方法名與類名相同,就像C#所作的那樣,另一種是徹底消滅所有的構(gòu)造器,就像Smalltalk所作的那樣。