![Java无难事:详解Java编程核心思想与技术](https://wfqqreader-1252317822.image.myqcloud.com/cover/59/35011059/b_35011059.jpg)
5.5 访问控制
访问控制分为类的访问控制和类成员的访问控制。
5.5.1 类的访问说明符
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_28.jpg?sign=1739291900-Ew277pcIKM06GCKHGexdcLxvtlYws3ed-0-9ef647e78ecb789488e63c69ccb8f726)
扫码看视频
类的访问说明符其实我们都已经用过了,只有两种:public和default(不加访问说明符时),前者让该类成为公共的类,可以被任意包中的类所访问;后者让该类具有包访问权限,只能被同一个包中的类所访问。
代码5.10展示了在com.sunxin包中定义的两个类,Animal类具有默认访问权限(即包访问权限),Fish类具有public访问权限。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_29.jpg?sign=1739291900-FCYFRMMPWQ0Vf2HylUkXhbZdXMsImhRU-0-230bc3cd785ef855b52de0bfee13fa65)
由于Animal类和Fish类在同一个包中,所以Fish类是可以直接访问Animal类的。同时也不要忘记public类必须保存在与类名相同名字的源文件中。
接下来我们在org.sx包中定义一个类Zoo,分别访问Animal类和Fish类,如代码5.11所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_30.jpg?sign=1739291900-aMIyt8xlqStoz7RUETCWQtDAlE4p1VOj-0-50e63ac303a7f47709c56617bb0085d9)
上述代码在编译时,会提示如图5-9所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_31.jpg?sign=1739291900-xJOgi5DnDbTIRKtaHwPlPXhiyGYfMbA8-0-6cb2a5744582db6748fab1a8e831c4c3)
图5-9 在另一个包中访问包访问权限的类报错
在实际开发中,一般都把类声明为public,只是在设计一些基础类库的时候,某些类只用于为同一个包中的其他类提供服务,这时候会将这些类设定为包访问权限。
5.5.2 类成员的访问说明符
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_32.jpg?sign=1739291900-aKRIJS4wZFSGst8rlnT0NnzDGMET2elc-0-d5b1682dbcab8ec2cee5d9344b676e1b)
扫码看视频
我们已经见过三种类成员的访问说明符了,即:public、default(不加访问说明符时)和private。还有一种是protected,接下来,我们分别看一下这四种访问说明符。
1.public
类的public成员作为公共的成员,可以被其他类随意访问,public方法作为对象提供给外部的访问接口,很少情况会把类的实例变量设置为public。
代码5.12和代码5.13演示了不同包中的类访问类中的public方法。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_33.jpg?sign=1739291900-ooSOtu5syjECWy2jauDWWqJMh6VcJzr6-0-87278d37cd19d8e299a6af625d8fefad)
2.protected
proctected即受保护的访问权限,也称为继承访问权限,使用protected说明的成员可以在子类中被访问。除此之外,protected还提供了包访问权限,也就是说,在同一个包中的其他类(没有继承关系)也可以访问protected成员,这一点是和C++中的protected访问权限不同的。
我们看代码5.14和代码5.15。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_34.jpg?sign=1739291900-X8Ocni32ElALMQD6yGVEHm8UnyVecFZC-0-6dc3ed6006ec1a23fc05d2b6924eb10b)
在编译B.java时,编译器会提示如图5-10所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_35.jpg?sign=1739291900-Ar6ycSMTyffpP6zZHtwFuv7zNZfCjXgg-0-3232c178d4c77b8a9ced165fa79eff47)
图5-10 在不同的包中访问类的protected方法引发错误
修改类B的代码,让类B从类A继承,如代码5.16所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_36.jpg?sign=1739291900-6KL8QK2TfK6toA389e0sisxpsdWCaUvP-0-5cbd306f9663a918f88958943b566c09)
现在类B从类A继承,也就继承了proMethod方法。再次编译B.java,可以发现一切正常。当然,你也可以直接在main方法中构造类B的对象,然后调用proMethod方法,前面章节已经说过,虽然main方法比较特殊,但是将它放在哪个类中,就可以把这个方法看成该类的静态成员方法。因此,在main方法中通过类B的对象调用proMethod方法也是可以的,仍然是在子类中的调用。
假如先在main方法中构造类A的对象,然后通过该对象调用proMethod方法,是否可行?如下面的代码所示:
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_37.jpg?sign=1739291900-ePp2gyA3lNhLK0SZR6c1zRC2C7dZ9P4Z-0-432c39fea3413f5017528eba58ada762)
读者自行测试一下,就能更好地理解protected访问权限可以在子类中被访问的真正含义。
接下来再编写一个类C,与类A在同一个包中,但是没有继承关系,在类C中访问类A的proMethod方法,如代码5.17所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_38.jpg?sign=1739291900-c3LGBA57LkrNLRn0sFodEkALSswQSTRK-0-774150e05631af548a8dea994d2e8589)
编译C.java,发现一切正常。说明在同一个包中的其他类是可以访问protected成员的,它们之间不需要有继承关系。
在设计类的继承体系结构时,某些方法或者数据成员只想让子类访问,而不希望其他类访问,那么就可以将这些成员声明为protected。
3.default
default访问权限即包访问权限,当类中的成员没有添加任何访问说明符时,即为默认访问权限。前面章节给出的代码如果没有使用访问说明符,那么这些类的成员都是默认访问权限,具有默认访问权限的类成员,只能被在同一个包中的其他类所访问。
代码5.18~代码5.20演示了具有默认访问权限的类成员访问情况。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_39.jpg?sign=1739291900-kMM9flYPlkZpmTdRNnX4Gl2L9Kl0en7s-0-722ffbd03098c11953ce2daa2a4366af)
B.java在编译时会提示如图5-11所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_40.jpg?sign=1739291900-JeUssJwrLt7irTDRYFj6jlHCvkN48Ta7-0-b5027a52a5466dcf5a536041a3af432b)
图5-11 在其他包中访问具有默认访问权限的方法报错
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_41.jpg?sign=1739291900-rPDeidydnydUVXKGT5EK0Kud0Q74RwSq-0-b43473c2edd78e6a7ffafe2a99a47aef)
类C与类A在同一个包中,所以可以访问类A的具有默认访问权限的方法。编译C.java,一切正常。
默认访问权限允许将包内所有相关的类组织在一起,这些类彼此之间可以互相调用,而包外的类则无法访问,这提供了一种代码组织的方式。
4.private
在第4.5节我们已经详细介绍过private访问权限,私有的成员只能在该类中被访问,这里我们就不再赘述了。
我们总结一下类成员的这四种访问说明符的访问范围,如表5-1所示。
表5-1 类成员的访问控制
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_42.jpg?sign=1739291900-3IABKNVEAe0NijdmZxx5LnXQKaBNVGdn-0-ae2629c9d94cc5922b8fef082a87d7b4)
注:√号代表可以访问。