有效的構(gòu)造函數(shù)調(diào)用 首先,為了對類型參數(shù)構(gòu)造合法的 new 表達式(如 new T()),必須確保我們調(diào)用的構(gòu)造函數(shù)對于 T 的每個實例化都有效。但由于我們只知道 T 是其已聲明界限的子類型,所以我們不知道 T 的某一實例化將有什么構(gòu)造函數(shù)。要解決這一問題,可以用下述三種方法之一:
class D< S> { C< S> makeC() { return new C< S>(); } }
現(xiàn)在,在類 D< S> 中,構(gòu)造了類 C< S> 的實例。然后,在類 C 的主體中,將調(diào)用 S 的不帶參數(shù)的構(gòu)造函數(shù)。這種不帶參數(shù)的構(gòu)造函數(shù)存在嗎?答案當然取決于 S 的實例化!
比方說,假如 S 被實例化為 String,那么答案是“存在”。假如它被實例化為 Integer,那么答案是“不存在”。但是,當編譯類 D 和 C 時,我們不知道其它類會構(gòu)造什么樣的 D< S> 實例化。即使我們有可用于分析的整個程序(我們幾乎從來沒有這樣的 Java 程序),我們還是必須進行代價相當高的流分析來確定潛在的構(gòu)造函數(shù)問題可能會出現(xiàn)在哪里。
此外,這一技術(shù)所產(chǎn)生的錯誤種類對于程序員來說很難診斷和修復。例如,假設程序員只熟悉類 D 的頭。他知道 D 的類型參數(shù)的界限是缺省界限(Object)。假如得到那樣的信息,他沒有理由相信滿足聲明類型界限(如 D< Integer>)的 D 的實例化將會導致錯誤。事實上,它在相當長的時間里都不會引起錯誤,直到最后有人調(diào)用方法 makeC 以及(最終)對 C 的實例化調(diào)用方法 makeT。然后,我們將得到一個報告的錯誤,但這將在實際問題發(fā)生很久以后 — 類 D 的糟糕實例化。
還有,對所報告錯誤的堆棧跟蹤甚至可能不包括任何對這個糟糕的 D 實例的方法調(diào)用!現(xiàn)在,讓我們假設程序員無權(quán)訪問類 C 的源代碼。他對問題是什么或如何修正代碼將毫無頭緒,除非他設法聯(lián)系類 C 的維護者并獲得線索。