第7章 方法

第38条:检查参数的有效性


每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制。应该把这些限制写到文档中,并且在这个方法体的开头处,通过显示的检查来实施

这些限制。养成这样的习惯是非常重要的。只要有效性检查有一次失败,你为必要的有效性检查所付出的的努力便都可以连本带利地得到偿还了。


第39条:必要时进行保护性拷贝


假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性设计程序。

保护性拷贝是在检查参数的有效性之前进行的并且有效性检查是针对拷贝之后的对象,而不是针对原始的对象。

保护性拷贝可能会带来相关的性能损失,这种说法并不总是正确的。如果类信任它的调用者不会修改内部的组件,可能因为类及其客户端都是同一个

包的双方,那么不进行保护性拷贝也是可以的。在这种情况下,类的文档中就必须清楚地说明,调用者绝不能修改受到影响。

即使跨越包的作用范围,也并不总是适合在将可变参数整合到对象中之前,对它进行保护性拷贝。有一些方法和构造器的调用,要求参数所引用的对象

必须有个显式的交接(handoff)过程。当客户端调用这样的方法时,它承诺以后不再直接修改该对象。如果方法或者构造器期望接管一个由客户端提供

的可变对象,它就必须在文档中明确地指明这一点。

如果类所包含的方法或者构造器的调用需要移交对象的控制权,这个类就无法让自身抵御恶意的客户端。只有当类和它的客户端之间有着互相的信任,或者

破坏类的约束条件不会伤害到除了客户端之外的其他对象时,这种类才是可以接受的。后一种情形的例子是包装类模式。根据包装类的本质特征,客户端

只需在对象被包装之后直接访问它,就可以破坏包装类的约束条件,但是,这么做往往只会伤害到客户端自己。

简而言之,如果类具有从客户端得到或者返回到客户端的可变组件,类就必须保护性地拷贝这些组件。如果拷贝的成本受到限制,并且类信任它的客户端

不会不恰当地修改组件,就可以在文档中指明客户端的职责是不得修改受到影响的组件,以此来代替保护性拷贝。


第40条:谨慎设计方法签名


谨慎地选择方法的名称。


方法的名称应该始终遵循标准的命名习惯。首要目标应该是选择易于理解,并且与同一个包中的其他名称风格一致的名称。第二个目标应该是选择易于理解的,

并且与同一个包中的其他名称风格一致的名称。第二个目标应该是选择与大众认可的名称(如果存在的话)相一致的名称。如果还有疑问,请参考Java类库的

API。尽管Java类库中的API也有大量的不一致的地方,考虑到这些Java类库的规模和范围,这是不可避免的,但它还是得到了相当程度的认可。


不要过于追求提供遍历的方法


每个方法都应该尽其所能。方法太多会使类难以学习、使用、文档化、测试和维护。对于接口而言,这无疑是正确的,方法太多会使接口实现者和接口用户的工作

变得复杂起来。对于类和接口所支持的每个动作,都提供一个功能齐全的方法。只有当一项操作被经常用到的时候,才考虑为它提供快捷方式。如果不能确定,还是

不提供快捷为好。


避免过长的参数列表


目标是四个参数,或者更少。大多数程序员都无法记住更长的参数列表。如果你编写的许多方法都超过了这个限制,你的API就不太便于使用,除非用户不停地参考

它的文档。现代的IDE会有所帮助,而且,当他们不小心弄错了参数顺序时,他们的程序仍然可以编译和运行,只不过这些程序不会按照作者的意图进行工作。


有三种方法可以缩短多长的参数列表。第一种是把方法分解成多个方法,每个方法只需要这些参数的一个子集。如果不小心,这样做会导致方法过多。但是通过提升

它们的正交性,还可以减少方法的数目。

缩短长参数列表的第二种方法是创建辅助类,用来保存参数的分组。这些辅助类一般为静态成员类。如果一个频繁出现的参数序列可以被看作是代表了某个独特的实体,

则建议使用这种方法。


结合了前两种方法特征的第三种方法是,从对象构建到调用都采用Builder模式。如果方法带有多个参数,尤其是当它们中有些是可选的时候,最好定义一个对象来表

示所有参数,并允许客户端在这个对象上进行多次“setter”调用,每次调用都设置一个参数,或者设置一个较小的相关的集合。一旦设置了需要的参数,客户端就

调用对象的“执行”方法,它对参数进行最终的有效性检查,并执行实际的计算。


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


第41条:慎用重载


对于重载方法(overloaded  method)的选择是静态的,而对于被覆盖的方法(overridden  method)的选择则是动态的。

简而言之,“能够重载方法”并不意味着就“应该重载方法”。一般情况下,对于多个具有相同参数数目的方法来说,应该尽量避免重载方法。在某些情况下,

特别是涉及构造器的时候,要遵循这条建议也许是不可能的。在这种情况下,至少应该避免这种情形。


第42条:慎用可变参数


不必改造具有final数组参数的每个方法:只当确实是在数量不定的值上执行调用时才使用可变参数。

简而言之,在定义参数数目不定的方法时,可变参数方法是一种很方便的方式,但是它们不应该被过度滥用。如果使用不当,会产生混乱的结果。



第43条:返回零长度的数组或者集合,而不是null


对于一个返回null而不是零长度数组或者集合的方法,几乎每次用到该方法时都需要这种曲折的处理方式。这样做很容易出错,因为编写客户端程序的程序员

可能忘记写这种专门的代码来处理null返回值。这样的错误也许几年都不会被注意到,因为这样的方法通常返回一个或者多个对象。返回null而不是零长度的

数组也会返回数组或者集合的方法本身变得更加复杂,这一点虽然不是特别重要,但是也值得注意。

有时候有人认为:null返回值比零长度数组更好,因为它避免了分配数组所需要的开销。这种观点是站不住脚的,原因有两点。第一,在这个级别上担心性能

问题是不明智的,除非分析表明这个方法正是造成性能问题的真正源头。第二,对于不返回任何元素的调用,每次都返回同一个零长度数组是有可能的,因为

零长度是不可变的,而不可变对象有可能被自由地共享。


简而言之,返回类型为数组或集合的方法没理由返回null,而不是返回一个零长度的数组或者集合。这种习惯做法(指返回null)很有可能是从C程序设计语言

中沿袭过来的,在C语言中,数组长度是与实际的数组分开返回的。在C语言中,如果返回的数组长度为零,再分配一个数组就没有任何好处。


第44条:为所有导出的API元素编写文档注释


为了正确地编写API文档,必须在每个被导出的类、接口、构造器、方法和域声明之前增加一个文档注释。

方法的文档注释应该简洁地描述出它和客户端之间的约定。

类的导出API有两个特征经常被人忽视,即线程安全性和可序列化性。

为了降低文档注释中出错的可能性,一种简单的办法是通过一个HTML有效性检查器(HTML validity checker)来运行由Javadoc产生的HTML文件。这样可以

检测出HTML标签的许多不正确用法,以及应该被转义的HTML元字符。

关于文档注释有一点需要特别注意。虽然为所有导出的API元素提供文档注释是必要的,但是这样做并非永远就足够了。对于由多个相互关联的类组成的复杂

API,通常有必要用一个外部文档来描述该API的总体结构,对文档注释进行补充。如果有这样的文档,相关的类或者包文档注释就应该包含一个对这个外部文档

的链接。

简而言之,要为API编写文档,文档注释是最好、最有效的途径。对于所有可导出的API元素来说,使用文档注释应该被看作是强制性的。要采用一致的风格来遵循

标准的约定。记住,在文档注释内部出现任何HTML标签都是允许的,但是HTML元字符必须要进过转义。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值