要区别设计良好的模块与设计不好的模块,最重要的的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节。设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰地隔离开来。然后,模块之间只通过他们的API进行通信,一个模块不需要知道其他模块的内部工作情况。这个概念被称为信息隐藏(information hiding)或封装(encapsulation),是设计模式的基本原则之一。
Java程序设计语言提供了许多机制(facility)来协助信息隐藏。访问控制(access control)机制决定了类、接口和成员的可访问性(accessibility)。实体的可访问性是由该实体声明所在的位置,以及该实体声明中出现的访问修饰符(private、protected和public)共同决定的。正确的使用这些修饰符对于实现信息隐藏是非常关键的。
第一规则很简单:尽可能地使每个类或者成员不被外界访问。换句话说,应该使用与你正在编写的软件对应功能相一致的、尽可能最小的访问级别。
对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别:包级私有的(package-private)和公有的(public)。如果你用public修饰符声明了顶层类或者接口,那他就是公有的;否则,他将是包级私有的。如果类或者接口能够被做成包级私有的,他就应该被做成包级私有的。通过把类或者接口做成包级私有,它实际上成了这个包的实现的一部分,而不是该包导出的API的一部分,在以后的发型版本中,可以对它进行修改、替换或者删除,而无需担心会影响到现有的客户端程序。如果你把它做成公有的,你就有责任永远支持它,以保持他们的兼容性。
如果一个包级私有的顶层类(或者接口)只是在某一个类的内部被用到,应该考虑使他成为唯一使用它的那个类的私有嵌套类。这样可以将他的可访问范围从包中所有类缩小到了使用他的那个类。然而,降低不必要公有类的可访问性,比降低包级私有的顶层类的更重要的多:因为公有类是包的API的一部分,而包级私有的顶层类则已经是这个包的实现的一部分。
对于成员(域、方法、嵌套类和嵌套接口)有四种可能访问级别,下面按照可访问性的递增顺序罗列出来:
- 私有的(private)—— 只有在声明该成员的顶层类内部才可以访问这个成员。
- 包级私有的(package-private)—— 声明该成员的包内部的任何类都可以访问这个成员。从技术上讲,它被称为“缺省(default)访问级别”,如果没有为成员指定访问修饰符,就采用这个访问级别。
- 受保护的(protected)—— 声明该成员的类的子类可以访问这个成员(但有一些限制),并且,声明该成员的包内部的任何类也可以访问这个成员。
- 公有的(public)—— 在任何地方都可以访问该成员。