
5.5 访问控制
访问控制分为类的访问控制和类成员的访问控制。
5.5.1 类的访问说明符

扫码看视频
类的访问说明符其实我们都已经用过了,只有两种:public和default(不加访问说明符时),前者让该类成为公共的类,可以被任意包中的类所访问;后者让该类具有包访问权限,只能被同一个包中的类所访问。
代码5.10展示了在com.sunxin包中定义的两个类,Animal类具有默认访问权限(即包访问权限),Fish类具有public访问权限。

由于Animal类和Fish类在同一个包中,所以Fish类是可以直接访问Animal类的。同时也不要忘记public类必须保存在与类名相同名字的源文件中。
接下来我们在org.sx包中定义一个类Zoo,分别访问Animal类和Fish类,如代码5.11所示。

上述代码在编译时,会提示如图5-9所示的错误。

图5-9 在另一个包中访问包访问权限的类报错
在实际开发中,一般都把类声明为public,只是在设计一些基础类库的时候,某些类只用于为同一个包中的其他类提供服务,这时候会将这些类设定为包访问权限。
5.5.2 类成员的访问说明符

扫码看视频
我们已经见过三种类成员的访问说明符了,即:public、default(不加访问说明符时)和private。还有一种是protected,接下来,我们分别看一下这四种访问说明符。
1.public
类的public成员作为公共的成员,可以被其他类随意访问,public方法作为对象提供给外部的访问接口,很少情况会把类的实例变量设置为public。
代码5.12和代码5.13演示了不同包中的类访问类中的public方法。

2.protected
proctected即受保护的访问权限,也称为继承访问权限,使用protected说明的成员可以在子类中被访问。除此之外,protected还提供了包访问权限,也就是说,在同一个包中的其他类(没有继承关系)也可以访问protected成员,这一点是和C++中的protected访问权限不同的。
我们看代码5.14和代码5.15。

在编译B.java时,编译器会提示如图5-10所示的错误。

图5-10 在不同的包中访问类的protected方法引发错误
修改类B的代码,让类B从类A继承,如代码5.16所示。

现在类B从类A继承,也就继承了proMethod方法。再次编译B.java,可以发现一切正常。当然,你也可以直接在main方法中构造类B的对象,然后调用proMethod方法,前面章节已经说过,虽然main方法比较特殊,但是将它放在哪个类中,就可以把这个方法看成该类的静态成员方法。因此,在main方法中通过类B的对象调用proMethod方法也是可以的,仍然是在子类中的调用。
假如先在main方法中构造类A的对象,然后通过该对象调用proMethod方法,是否可行?如下面的代码所示:

读者自行测试一下,就能更好地理解protected访问权限可以在子类中被访问的真正含义。
接下来再编写一个类C,与类A在同一个包中,但是没有继承关系,在类C中访问类A的proMethod方法,如代码5.17所示。

编译C.java,发现一切正常。说明在同一个包中的其他类是可以访问protected成员的,它们之间不需要有继承关系。
在设计类的继承体系结构时,某些方法或者数据成员只想让子类访问,而不希望其他类访问,那么就可以将这些成员声明为protected。
3.default
default访问权限即包访问权限,当类中的成员没有添加任何访问说明符时,即为默认访问权限。前面章节给出的代码如果没有使用访问说明符,那么这些类的成员都是默认访问权限,具有默认访问权限的类成员,只能被在同一个包中的其他类所访问。
代码5.18~代码5.20演示了具有默认访问权限的类成员访问情况。

B.java在编译时会提示如图5-11所示的错误。

图5-11 在其他包中访问具有默认访问权限的方法报错

类C与类A在同一个包中,所以可以访问类A的具有默认访问权限的方法。编译C.java,一切正常。
默认访问权限允许将包内所有相关的类组织在一起,这些类彼此之间可以互相调用,而包外的类则无法访问,这提供了一种代码组织的方式。
4.private
在第4.5节我们已经详细介绍过private访问权限,私有的成员只能在该类中被访问,这里我们就不再赘述了。
我们总结一下类成员的这四种访问说明符的访问范围,如表5-1所示。
表5-1 类成员的访问控制

注:√号代表可以访问。