這是我今天在工作中碰到的問題,是關於繼承和多態的。同事對項目中的一項基礎功能進行了重構,可是當我們從CVS伺服器上更新了項目原始碼並編譯了之後,發現這項功能已不能正常工作了。先撇開這個同事所犯的錯誤(對代碼進行重構後沒有測試他的新代碼就上傳到了CVS伺服器上)不說,在這裡我就說說這個問題所帶出來的JAVA konwhow.由於我們的項目比較複雜,我在這裡採取比較簡單的例子來講解這個問題。首先,我們有2個類:supper.TestSupper.java 和sub.TestSub.java。他們的代碼是這樣的:package supper;public class TestSupper { String getString() { return "This is supper class."; }}-----------------------------------package sub;import supper.TestSupper;public class TestSub extends TestSupper { public String getString(){ return "This is sub class."; }}十分簡單,第一眼看上去,你會覺得TestSub繼承了TestSupper並且重寫getString()方法。現在我們寫一個測試程式:package supper;import sub.TestSub;public class Test { public static void main(String[] args) { TestSupper test = new TestSub(); System.out.println(test.getString()); }}請注意啊!測試程式和TestSupper在同一個包裡。從理論上說,這個測試程式應該輸出“This is sub class”,因為test的實體是一個TestSub對象而不是TestSupper。所以,當我們調用test.getString()時,真正被調用的應該是TestSub裡的getString()。可是事實如何呢?輸出是"This is supper class."!為什麼會這樣的?原因很簡單,因為在TestSupper裡方法getString()的標籤(signature)是"default",是預設的不用寫出來。這導致這個方法只能在這個包裡面可見。TestSub雖然繼承了TestSupper,卻沒有辦法“看見”getString()方法,因為TestSub在另外一個包裡。所以當我們在測試程式裡調用test.getString(),程式首先會尋找TestSub中是否重寫了這個方法,在這裡請一定要注意標籤是default的,當然是沒有發現。結果程式就會調用父類的相應方法,故父類中的結果就被輸出了。解決的辦法很簡單,但凡是要被重寫的方法一定不能定義成“default”,最少要定義成"protected”.如果你是在使用Eclipse的話,你可以在eclipse中進行設定,把這種情況視為Error就可以避免這種錯誤的產生。方法是:window ->preferences -> style ->methods overridden but not pachage visible這項選為Error。我用的是eclipse3.0。後話別看這是個很小的問題,而且很簡單,一看就明白,可是當系統出現了問題,而你要在幾百個類中尋找到問題所在的時候,這種不易察覺的錯誤絕對是致命的。尋找這個錯誤花了我們2個人天!可怕吧!