![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=1739137427-dlQZMxuBOKfDLQoODMrlkGicEdhKoIMX-0-3351c946bdafa291ebffeadc933cffa1)
扫码看视频
类的访问说明符其实我们都已经用过了,只有两种:public和default(不加访问说明符时),前者让该类成为公共的类,可以被任意包中的类所访问;后者让该类具有包访问权限,只能被同一个包中的类所访问。
代码5.10展示了在com.sunxin包中定义的两个类,Animal类具有默认访问权限(即包访问权限),Fish类具有public访问权限。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_29.jpg?sign=1739137427-RG1cmFSzTr7XiKZRqz6ceGvkSODRuCrA-0-e2c6ac087071a0320b71dab6ba57fbf4)
由于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=1739137427-ETbcmwvezp3JUoe8Hx8PTSfzBZJapuKc-0-4aaae5a48555d578414a5bde1c0455cc)
上述代码在编译时,会提示如图5-9所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_31.jpg?sign=1739137427-STWmqJYaGuGjKZzCuJw9sK3TZcHZmMRw-0-39c08c70da84a6a91c58d9a94400094d)
图5-9 在另一个包中访问包访问权限的类报错
在实际开发中,一般都把类声明为public,只是在设计一些基础类库的时候,某些类只用于为同一个包中的其他类提供服务,这时候会将这些类设定为包访问权限。
5.5.2 类成员的访问说明符
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_32.jpg?sign=1739137427-ISpkh8JjHpwbxtd9lVvrRGSLSD9JBHrl-0-e64676f9017bcb79b9b2cebe8df3c76b)
扫码看视频
我们已经见过三种类成员的访问说明符了,即: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=1739137427-H5xC6sbWbFBbDfnjuQCAOJlaFgyHyELO-0-261d397fe0e59ce12c51808dc2dd0180)
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=1739137427-b5yojUAqCxQD8Iojb0tVk9M09MlKNBR4-0-05f7868c2a0966d9b5a349e11c07eff7)
在编译B.java时,编译器会提示如图5-10所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_35.jpg?sign=1739137427-BiAPtNeGBITRrzSSEgSHRYDFOBZtBjpI-0-5620a8665d6d95dacd1b04bee38edf3b)
图5-10 在不同的包中访问类的protected方法引发错误
修改类B的代码,让类B从类A继承,如代码5.16所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_36.jpg?sign=1739137427-OAbfk9WPmcDPSaKZHvxHb1IZTMSo0UO9-0-931a8dc146e22b23ad4eb76351bacae0)
现在类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=1739137427-UngNZycvjZplL4Hartd6Km5yDS7QgOEu-0-7b691970f587e3010882e15da550e58b)
读者自行测试一下,就能更好地理解protected访问权限可以在子类中被访问的真正含义。
接下来再编写一个类C,与类A在同一个包中,但是没有继承关系,在类C中访问类A的proMethod方法,如代码5.17所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_38.jpg?sign=1739137427-MjdcmV2mDVQTCizjY8R5uTjkdOxOVv2E-0-c46064c1b21ea488c06432113f95da04)
编译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=1739137427-s2LgmP0YoToWrtM1PxpF5lmdnl3TIDXb-0-0ee6d102af3d9bbca549c6b0ff8d7e0b)
B.java在编译时会提示如图5-11所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_40.jpg?sign=1739137427-xgxp4TdF4ukow9nZxy5MJBaHWzWgKD3Z-0-5da5e002ebce12cb755ead8639b280ae)
图5-11 在其他包中访问具有默认访问权限的方法报错
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt005_41.jpg?sign=1739137427-z6AFt7CZ68Pjj0KZqYvr0QiyScgDlMDf-0-3bb8bca61d759a050a1b0ac94701f8fc)
类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=1739137427-p68ZWMRs2bzTyNE0tJUVSyX44cJrKsRr-0-ebdf9d677da33784f6b525b172efe7dc)
注:√号代表可以访问。