class D< S> { C< S> makeC() { return new C< S>(); } }
现在,在类 D< S> 中,构造了类 C< S> 的实例。然后,在类 C 的主体中,将调用 S 的不带参数的构造函数。这种不带参数的构造函数存在吗?答案当然取决于 S 的实例化!
比方说,假如 S 被实例化为 String,那么答案是“存在”。假如它被实例化为 Integer,那么答案是“不存在”。但是,当编译类 D 和 C 时,我们不知道其它类会构造什么样的 D< S> 实例化。即使我们有可用于分析的整个程序(我们几乎从来没有这样的 Java 程序),我们还是必须进行代价相当高的流分析来确定潜在的构造函数问题可能会出现在哪里。
此外,这一技术所产生的错误种类对于程序员来说很难诊断和修复。例如,假设程序员只熟悉类 D 的头。他知道 D 的类型参数的界限是缺省界限(Object)。假如得到那样的信息,他没有理由相信满足声明类型界限(如 D< Integer>)的 D 的实例化将会导致错误。事实上,它在相当长的时间里都不会引起错误,直到最后有人调用方法 makeC 以及(最终)对 C 的实例化调用方法 makeT。然后,我们将得到一个报告的错误,但这将在实际问题发生很久以后 — 类 D 的糟糕实例化。
还有,对所报告错误的堆栈跟踪甚至可能不包括任何对这个糟糕的 D 实例的方法调用!现在,让我们假设程序员无权访问类 C 的源代码。他对问题是什么或如何修正代码将毫无头绪,除非他设法联系类 C 的维护者并获得线索。