下面我们来讨论一下有关方法设计的几个方面,下面说的几个要点大多数都是应用在构造函数中,当然也使用于普通方法,我们追求的依然是程序的可用性,健壮性和灵活性。 

Item 23:检查参数的有效性

非公有的方法我们应该用断言的方法来检查它的参数,而不是使用通常大家所熟悉的检查语句来检测。如果我们使用的开发平台是JDK1.4或者更高级的平台,我们可以使用assert结构;否则我们应该使用一种临时的断言机制。

有些参数在使用过程中是先保存起来,然后在使用的时候再进行调用,构造函数正是这种类型的一种体现,所以我们通常对构造函数参数的有效性检查是非常仔细的。

Item 24:需要时使用保护性拷贝

众所周知,JAVA在代码安全性方面较C/C++有显著的提高,缓冲区溢出,数组越界,非法指针等等,我们的JAVA都有一个很完善的机制来进行免疫,但是这并不代表我们不必去考虑JAVA的安全性,即便在安全的语言,如果不采取措施,还是无法使自己与其他类隔开。假设类的客户会尽一切手段来破坏这个类的约束条件,在这样的前提下,你必须从保护性的方面来考虑设计程序。通过大量的程序代码研究我们得出这样的结论:对于构造性函数的每个可变参数进行保护性拷贝是必要的。需要注意的是,保护性拷贝是在检查参数的有效性之前 进行的,并且有效性检查是针对拷贝之后的对象,而不是原始的对象。对于“参数类型可以被不可信方子类化”的情况,不要用clone方法来进行参数的保护性拷贝。

对于参数的保护性拷贝并不仅仅在于非可变类,当我们编写一个函数或者一个构造函数的时候,如果它要接受客户提供的对象,允许该对象进入到内部数据结构中,则有必要考虑一下,客户提供的对象是否是可变的,如果是,则要考虑其变化的范围是否在你的程序所能容纳的范围内,如果不是,则要对对象进行保护性拷贝,并且让拷贝之后的对象而不是原始对象进入到数据结构中去。当然最好的解决方法是使用非可变的对象作为你的对象内部足见,这样你就可以不必关心保护性拷贝问题了。):

Item 25:谨慎使用设计方法的原型

(1)谨慎的选择方法的名字:即要注意首先要是易于理解的,其次还要与该包中的其他方法的命名风格相一致,最后当然要注意取一个大众所认可的名字。

(2)不要追求提供便利的方法:每一个方法都应该提供其应具备的功能点,对于接口和类来方法不要过多,否则会对学习使用维护等等方面带来许多不必要的麻烦,对于每一个类型所支持的每一个动作,都提供一个功能完全的方法,只有一个方法过于频繁的使用时,才考虑为它提供一个快捷方法。

(3)避免过长的参数列表:通常在实践中,我们以三个参数作为最大值,参数越少越好,类型相同的长参数列尤其影响客户的使用,两个方法可以避免过长的参数这样的情况发生,一是把一个方法分解成多个,每一个方法只要求使用这些参数的一个子集;二是创建辅助类,用来保存参数的聚集,这些辅助类的状态通常是静态的。

对于参数类型,优先使用接口而不是类。

这样做的目的是避免影响效能的拷贝操作。

谨慎的使用函数对象。

创建函数对象最容易的方法莫过于使用匿名类,但是那样会带来语法上混乱,并且与内联的控制结构相比,这样也会导致功能上的局限性。 

Item 26:谨慎的使用重载

到底是什么造成了重载机制的混淆算法,这是个争论的话题,一个安全而保守的方法是,永远不要导出两个具有相同参数数目的重载方法。而对于构造函数来说,一个类的多个构造函数总是重载的,在某些情况下,我们可以选择静态工厂,但是对于构造函数来说这样做并不总是切合实际的。

当涉及到构造函数时,遵循这条建议也许是不可能的,但我们应该极力避免下面的情形:

同一组参数只需要经过类型的转换就可以传递给不同的重载方法。如果这样做也不能避免的话,我们至少要保证一点:当传递同样的参数时,所有的重载方法行为一致。如果不能做到这一点,程序员就不能有效的使用方法或者构造函数。 

Item 27:返回零长度的数组而不是null

因为这样做的原因是编写客户程序的程序员可能忘记写这种专门的代码来处理null返回值。没有理由从一个取数组值的方法中返回null,而不是返回一个零长度数组。

Item 28:为所有导出的API元素编写文档注释

不爱写注释可能是大多数程序员新手的通病(包括偶哈~),但是如果想要一个API真正可用,就必须写一个文档来说明它,保持代码和文档的同步是一件比较烦琐的事情,JAVA语言环境提供了javadoc工具,从而使这个烦琐的过程变得容易,这个工具可以根据源代码自动产生API文档。

为了正确得编写API文档,我们必须每一个被导出的类,接口,构造函数,方法和域声明之前加一个文档注释。

每一个方法的文档注释应该见解的描述它和客户之间的约定。