诊断Java代码: 连续初始化器错误模式 - 编程入门网
例中, RestrictedInt 的构造函数应带有一个 int ,以初始化它的 value 域。包含一个留有任何未被初始化的域的类构造函数,这种做法永远不会有好的理由。当从头编写类时,这并不是难以遵循的原则。
但是,如果您 必须处理一大堆代码库,而其中某个类并未在它的构造函数中初始化其所有域,并且代码库中到处是连续初始化器,那又该怎么办呢?我已经不止一次陷入到了这种境地。 当您束手无策时 不幸的是,这样一种情形,即处理其中某个类没有在它的构造函数中初始化所有域的旧代码库,比多数程序员所愿意处理的情形更常见。如果旧代码库很大,而且有损坏了的类的很多客户机,那您可能不会想修改构造函数说明,特别是如果代码的单元测试并不充足的话。不可避免地,您将在破坏了一些未编制文档的不变量之后作罢。 通常,在这种情形中,最好是抛开那些旧代码,从头做起!这听起来像疯言疯语,但您修补像那样的代码中的错误花去的时间很容易就能让重新编写代码所用的时间相形见绌。有很多次,我都煞费苦心地处理带有那种问题的庞大的旧代码库,但最终,我都只好放弃,但愿自己要是从头做起就好了。 但如果不能选择抛开那些代码的话,我们仍然可以通过结合以下简单的做法来尝试控制出错的可能性: 把域初始化成(非空)缺省值。 包含额外的构造函数供使用。 在类中包含一个 isInitialized 方法。 构造特殊的类来代表缺省值。 让我们来看看为什么应该采用这些做法。 把域初始化成(非空)缺省值 通过把缺省值填充到域,您确保了类的实例在任何时候都处于定义良好的状态。这一做法对于除非另行指定,否则就取空值的引用类型尤其重要。 为什么?因为滥用空值不可避免地会导致 NullPointerException 。而 NullPointerException 是很糟糕的。一个原因是,这些异常几乎不提供关于一个错误的真正起因的信息。另一个原因是,它们常常在离错误的实际起因很远的地方被抛出。 要不惜一切代价避免它们。如果您决定要使用空值,以便您可以发出某个类尚未被完全初始化的信号,那请您参阅我的关于 Null Flag 错误模式的文章获取帮助。 诊断Java代码: 连续初始化器错误模式(3)时间:2011-02-11 IBM Eric E. Allen包含额外的构造函数 当您包含额外的构造函数时,您可以在新的上下文中使用它们,在那里您不必包含新的连续初始化。仅仅是因为有些上下文被限制成必须使用连续初始化,其它上下文则不必为此付出代价。 在类中包含一个 isInitialized 方法 可以在类中包含一个 isInitialized 方法,以允许迅速判断某个实例是否已经被初始化了。在编写需要连续初始化的类时,这样一个方法基本上总是一个好主意。 对于您不是自己维护这些类的情况,您甚至可以把这样的 isInitialized 方法放到您自己的实用程序类中。毕竟,如果一个实例未被初始化,并且其结果可以从外部观察到,那么您就可以写一个方法来检查这个结果(即使它要求采用一般认为是不明智的实践 ― 捕获 RuntimeException )。 构造特殊的类来代表缺省值 不是允许用空值来填充域,而是允许构造特殊的类(很可能是用 Singletons)来代表缺省值。然后把这些类的实例填充到缺省构造函数的域。您不但将降低抛出 NullPointerException 的可能性,而且,如果这些域被不恰当地访问了,您还将能够精确地掌握真正发生了什么错误。 例如,我们可以修改 RestrictedInt 类如下: 清单 2. 带 NonValue 的 RestrictedInt
|
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |