国内java书籍在介绍到访问控制符时很多只是简单地引用如下表格:
| public | protected | default | private |
同类 | T | T | T | T |
同包 | T | T | T | |
子类(不同包) | T | T | ||
不同包中无继承关系的类 | T |
(以下引自http://www.bianceng.cn/Programming/Java/201003/15861.htm)
从理论角度出发,访问控制符是面向对象封装性的重要表现,其作用是说明被声明的内容(类、属性、方法和构造方法)的访问权限,就像发布的文件一样,在文件中标注机密,就是说明该文件可以被那些人阅读。合理的使用访问控制符,可以通过降低类和类之间的耦合性(关联性)来降低整个项目的复杂度,也便于整个项目的开发和维护。具体的实现就是通过访问控制符将类中会被其它类调用的内容开放出来,而把不希望别人调用的内容隐藏起来,这样一个类开放的信息变得比较有限,从而降低了整个项目开放的信息,另外因为不被别人调用的功能被隐藏起来,在修改类内部隐藏的内容时,只要最终的功能没有改变,即使改变功能的实现方式,项目中其它的类不需要更改,这样可以提高了代码的可维护性,便于项目代码的修改。
1、public,private一般不会理解有误,光从名字就能看出其作用范围。public修饰的属性或方法能在任何位置被访问到,可以戏称其与互联网行业一致的开放、share的心态。只不过开放过头会导致某些安全问题,例如用户隐私等等,所以就需要private来保护重要资源,private修饰的属性或方法仅能在类内部访问或使用(当然使用getter、setter方法也能够操作对象的private属性),而且子类也无法继承到父类的private属性和方法。这里同时说明的是,private不能用于修饰类名,很容易理解的是:如果一个类本身就是私有的,那完全用不上,我还声明它做什么呢?!
2、default相对private开放一点,它修饰的属性方法只能在同一个包中访问。同时也只能被同包子类继承。可以有效减少包与包之间的耦合。当属性或方法没有指定访问修饰符时,它就是default的,java中default关键字另有用途,因此当我们要将属性声明为default时,不写访问修饰符就是了。
3、最容易混乱的是protected关键字,按照上面的表格,它可以被非同包的子类访问。而实际情况是它修饰的属性方法能被非同包子类继承,但是在该子类当中的父类类型的对象却无法访问protected属性和方法。这句话说得很拗口,引用《Java in a nutshell》的一段话:
protected access requires a little moreelaboration. Suppose class A declares a protected field x and is extended by aclass B, which is defined in a different package (this last point isimportant). Class B inherits the protected field x, and its code can accessthat field in the current instance of B or in any other instances of B that thecode can refer to. This does not mean, however, that the code of class B canstart reading the protected fields of arbitrary instances of A! If an object isan instance of A but is not an instance of B, its fields are obviously notinherited by B, and the code of class B cannot read them.
同时结合代码来看会清晰很多:
①父类:
package com.java.base.accesscontrol;
public class AccessControlFather {
public String publicStr = "public"; //public属性
protected String protectedStr = "default"; //protected属性
String defaultStr = "default"; //default属性
private String privateStr = "private"; //private属性
}
②同包子类:
package com.java.base.accesscontrol;
public class AccessControlChild extends AccessControlFather{
public void testFun()
{
publicStr = "inherit public"; //父类的public属性能被继承
String testPublicStr = super.publicStr; //可以使用super关键字访问父类的public属性
protectedStr = "inherit protected"; //父类的private属性能被继承
AccessControlFather acf = new AccessControlFather();
acf.publicStr = "child public"; //父类对象的public属性能被访问
acf.protectedStr = "child protected"; //父类对象的protected属性在同包子类中可以访问
}
}
③非同包子类:
package com.java.base.accesscontrol2;
import com.java.base.accesscontrol.AccessControlFather;
public class AccessControlChild2 extends AccessControlFather {
public void testFun()
{
// defaultStr = "child2 default"; //非同包子类不可继承default属性
protectedStr = "child2 protected"; //非同包子类继承了protected属性
AccessControlFather acf = new AccessControlFather();
// acf.protectedStr = "update child2 protected"; //非同包子类当中的父类对象的protected属性不可见,protected方法同理
}
}
由此可见,学习技术遇到争议处,多看英文经典原版和编写代码验证是最直接、印象最深刻的解决方案,“纸上的来终觉浅,绝知此事要躬行”也就是这么个道理吧。第一篇技术类博客到此为,mark纪念一下。