当字段被声明为 protected 类型时,子类中的成员函数可能会直接访问它,增加了类的耦合性。这使类更难维护和加强,所以应该尽量避免。字段不应被直接访问,而应采用存取成员函数(参见下文)访问。
可见性 | 说明 | 正确用法 |
public | 一个公共字段可被任何其他对象或者类中的成员函数访问。 | 尽量不要让字段公有。 |
protected | 被保护的字段可被它声明时所在的类及该类的子类的所有成员函数访问。 | 尽量不要让字段被保护。 |
private | 私有字段只可以被它声明时所在的类的其它成员函数调用,该类子类中的函数不可以调用。 | 所有的字段都应尽可能置为私有,由获取和设置成员函数(存取函数)访问。 |
所有的字段都应很好地加以注释,以便其他开发者理解它。要想有效地注释,以下的部分需要说明:
Ø 字段的说明。使用javadoc来描述字段的用途和约束。在注释中增加如下标签。
l @see
string
l @see
UR
l L@see
classname#methodname
Ø 注释出所有采用的不变量。字段中的不变量是指永远为“真”的条件。例如,字段 dayOfMonth 的不变量可能是它的值只能在 1 到 31 之间(显然,可以用基于某一年里的某个月份来限制这个字段值,使其变的更加复杂)。通过说明字段值的限制条件,有助于定义重要的业务规则,使代码更易理解。
Ø 示例。对于那些有复杂业务规则与之相关联的字段,应提供几个例子,使它们容易理解。一个例子常象一幅画:它抵得上几千个词语。
Ø 并行事件。对众多程序开发者来说,并行性是一个新而复杂的概念;事实上,即使对有经验的并行程序开发者来说,并行性也是一个老但却复杂的课题。最终结果是,如果应用了 Java 的并行编程特性,那么你应在程序中详细地注释出来。
Ø 可见性决策。如果声明了一个非私有字段,则应说明为什么要这样做。字段的可见性在上文中(第 5.1 节“字段的可见性”)讨论了,支持封装的存取成员函数的用法将在下文(第 5.3 节“使用存取成员方法”)中讨论。总的来说,最好能有一个好的理由解释为什么不将变量声明为私有类型。
例:
/**
* The current number of elements.
* must be non-negative, and less than or equal to capacity.
*/
protected int count_;
除了满足命名约定之外,适当地使用存取成员函数,即提供更新或访问字段值的成员函数,可以实现字段的可维护性。存取成员函数有两种:设置函数(也叫变化函数)和获取函数。设置函数修改变量的值,获取函数取到变量的值。存取成员函数通过以下方法提高类的可维护性:
Ø 更新字段。.每个字段只有几个单点要更新,这使得修改和检测都很容易。换句话说,字段已被封装。
Ø 获得字段的值。你完全控制着字段应怎样被访问以及被谁访问。
Ø 获取常量名和类名。在获取函数中封装常量值和类名,当这些值或名字改变时,只需更新获取函数内的值,而并非常量或者名字被使用处的每一行代码。
Ø 初始化字段。采用滞后初始化 (lazy initialization) 保证字段总能被初始化,并且只在需要时才初始化。
Ø 减少类与子类之间的耦合。 当子类通过它们相应的存取成员函数访问被继承的字段时,它可以不影响它的任何子类,而只修改超类字段的实现方式,这样有效地减少了超类与子类之间的耦合。存取函数减少了那种一旦超类被修改就会波及子类的“脆弱基类”的风险。
Ø 将变化封装到字段中。如果一个或者多个字段的业务规则变化了,可以只潜在地修改存取函数,就同样可以提供规则变化之前的功能。这一点使你很容易响应新的业务规则。
Ø 简化并行事件。如果采用了基于字段值的 waits 语句,那么设置成员函数提供了一个位置可包含 notifyAll。这让转向并行解决方案更加容易。
尽可能地让字段成为被保护 (protected) 类型,这样只有子类可以访问它们。仅当一个外部类需要访问一个字段时,才将相应的获取函数或设置函数置为公有。注意:获取函数是公有而设置函数是私有的情况经常发生。
静态字段,也叫类字段,应被赋予有效值,因为不能假定类的实例将在一个静态字段被访问之前生成。