访问权限控制
面向对象的核心思想之一就是封装,只把有限的方法和成员公开给别人,这也是迪米特法则的内在要求,使外部调用方对方法体的实现细节知道得尽可能少。如何实现封装呢?需要使用某些关键字来限制类外部对类内属性和方法的随意访问,这些关键字就是访问权限控制符。
JAVA中的访问权限包括四个等级,权限控制严格程度由低到高,如表2-2所示。
表2-2访问权限控制及可见范围
访问权限控制符 | 任何地方 | 包外子类 | 包内 | 类内 |
---|---|---|---|---|
public | OK | OK | OK | OK |
protected | NO | OK | OK | OK |
无 | NO | NO | OK | OK |
private | NO | NO | NO | OK |
· public: 可以修饰外部类、属性、方法,表示公开的、无限制的,是访问限制最松的一级,被其修饰的类、属性和方法不仅可以被包内访问,还可以跨类、跨包访问,甚至允许跨工程访问。
· protected: 只能修饰属性和方法,表示受保护的、有限制的,被其修饰的属性和方法能被包内及包子类访问。注意,即使并非继承关系,protected属性和方法在同一个包内也是可见的。
· 无: 即无任何访问权限控制符,如示例中的noneMethod方法,没有任何修饰符。千万不要说成default,它并非访问权限控制符的关键字,另外,在JDK8接口中引入了default默认方法的实现,更加容易混淆两者的释义。无访问权限控制符仅对包内可见。虽然无访问权限控制符还可以修饰外部类,但是定义外部类极少使用无控制符的方法,要么定义为内部类,功能内聚;要么定义公开类,即public class,包外也可以实例化。
· private:只能修饰属性、方法、内部类。表示"私有的",是访问限制最严格的一级,被其修饰的属性或方法只能在该类内部访问,子类、包类均不能访问,更不允许跨包访问。
由此可见,不同的访问权限控制符对应的可见范围不同。在定义类时,要慎重思考该方法、属性、内部类的访问权限,提倡严格访问范围。过于宽泛的访问范围不利于模块见解耦及未来的代码维护。试想,在进行代码重构时,private方法过旧,我们可以直接删除,且无后顾之忧。可是如果想删除一个public的方法,是不是要慎重有谨慎的检查是否被调用。变量就像自己的小孩,要尽量控制在自己的视线范围内,如果作用域太大,无限制地到处乱跑,就会担心其安危。因此,在定义类时,推荐访问控制级别从严处里:
(1) 如果不允许外部直接通过new创建对象,构造方法必须是private。
(2) 工具类不允许有public或default构造方法。
(3) 类非static成员变量并且与子类共享,必须是protected。
(4) 类非static成员变量并且仅在本类使用,必须是private。
(5) 类staitc成员变量如果仅在本类使用,必须是private。
(6) 若是static成员变量,必须考虑是否为final。
(7) 类成员方法只供类内部调用,必须是private。
(8) 类成员方法只对继承类公开,那么限制为protected。