诊断Java代码: 轻松掌握Java泛型,第3部分 - 编程入门网
例化。即使我们有可用于分析的整个程序(我们几乎从来没有这样的 Java 程序),我们还是必须进行代价相当高的流分析来确定潜在的构造函数问题可能会出现在哪里。
此外,这一技术所产生的错误种类对于程序员来说很难诊断和修复。例如,假设程序员只熟悉类 D 的头。他知道 D 的类型参数的界限是缺省界限( Object )。如果得到那样的信息,他没有理由相信满足声明类型界限(如 D<Integer> )的 D 的实例化将会导致错误。事实上,它在相当长的时间里都不会引起错误,直到最后有人调用方法 makeC 以及(最终)对 C 的实例化调用方法 makeT 。然后,我们将得到一个报告的错误,但这将在实际问题发生很久以后 ― 类 D 的糟糕实例化。 还有,对所报告错误的堆栈跟踪甚至可能不包括任何对这个糟糕的 D 实例的方法调用!现在,让我们假设程序员无权访问类 C 的源代码。他对问题是什么或如何修正代码将毫无头绪,除非他设法联系类 C 的维护者并获得线索。 第 3 种方法:修改语法以获得更详尽的界限 另一种可能性是修改语言语法以包括更详尽的类型参数界限。这些界限可以指定一组可用的构造函数,它们必须出现在参数的每一个实例化中。因而,在泛型类定义内部,唯一可调用的构造函数是那些在界限中声明的构造函数。 同样,实例化泛型类的客户机类必须使用满足对构造函数存在所声明的约束的类来这样做。参数声明将充当类与其客户机之间的契约,这样我们可以静态地检查这两者是否遵守契约。 与另外两种方法相比,该方法有许多优点,它允许我们保持第二种方法的可表达性以及与第一种方法中相同的静态检查程度。但它也有需要克服的问题。 首先,类型参数声明很容易变得冗长。我们或许需要某种形式的语法上的甜头,使这些扩充的参数声明还过得去。另外,如果在 Tiger 以后的版本中添加扩充的参数声明,那么我们必须确保这些扩充的声明将与现有的已编译泛型类兼容。 如果将对泛型类型的与类型相关的操作的支持添加到 Java 编程中,那么它采用何种形式还不清楚。但是,从哪种方法将使 Java 代码尽可能地保持健壮(以及使在它遭到破坏时尽可能容易地修正)的观点看,第三个选项无疑是最适合的。 然而, new 表达式有另一个更严重的问题。 多态递归 更严重的问题是类定义中可能存在 多态递归。当泛型类在其自己的主体中实例化其本身时,发生多态递归。例如,考虑下面的错误示例: 清单 2. 自引用的泛型类
假设客户机类创建新的 C<Object> 实例,并调用(比方说) nest(1000) 。然后,在执行方法 nest() 的过程中,将构造新的实例化 C<C<Object>> ,并且对它调用 nest(999) 。然后,将构造实例化 C<C<C<Object>>> ,以此类推,直到构造 1000 个独立的类 C 的实例化。当然,我随便选择数字 1000;通常,我们无法知道在运行时哪些整数将被传递到方法 nest 。事实上,可以将它们作为用户输入传入。 为什么这成为问题呢?因为如果我们通过为每个实例化构造独立类来支持泛型类型的与类型相关的操作,那么,在程序运行以前,我们无法知道我们需要构造哪些类。但是,如果类装入器为它所装入的每个类查找现有类文件,那么它会如何工作呢? 诊断Java代码: 轻松掌握Java泛型,第3部分(3)时间:2011-02-11 IBM Eric E. Allen同样,这里有几种可能的解决办法: 对程序可以产生的泛型类的实例化数目设置上限。 静态禁止多态递归。 在程序运行时随需构造新的实例化类。 第 1 种:对实例化数设置上限 我们对程序可以产生的泛型类的实例化数目设置上限 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |