
上篇文章--笔记20补充说明了前四点,这里接着来说剩下的两点。
要点如下:
5.访问权限修饰符可以修饰成员内部类
1).访问权限修饰符对内部类的访问限制与外部类的一般成员遵循一样的规则,具体请参考笔记10;
2).这里涉及到的子类是外部类的子类;
6.访问权限修饰符可以修饰成员内部类的成员变量和成员方法
1).成员内部类可由4种访问权限修饰符修饰,每种内部类的成员方法或变量也可由4种访问权限修饰符修饰,所以分16种情况来讨论;
2).修饰类时涉及到的子类是外部类的子类;修饰内部类的成员方法或变量时涉及到的子类是成员内部类的子类;
3).构造方法的默认修饰符与类一致;
4).在外部类的不同包子类中创建protected修饰的内部类的对象时,会提示构造方法不可见,这时要为该内部类添加public修饰的构造方法;
下面详细展开说明。
类Person中定义了4个成员内部类,分别由public、protected、默认、private修饰;并给这4个成员内部类分别添加4个成员方法,分别由public、protected、默认及private修饰。代码如下:
public class InnerClassPu { void printInCPuDef() { System.out.println("public inner class:default"); } public void printInCPuPu() { System.out.println("public inner class:public"); } protected void printInCPuPro() { System.out.println("public inner class:protected"); } private void printInCPuPri() { System.out.println("public inner class:private"); } } protected class InnerClassPro { void printInCProDef() { System.out.println("protected inner class:default"); } public void printInCProPu() { System.out.println("protected inner class:public"); } protected void printInCProPro() { System.out.println("protected inner class:protected"); } private void printInCProPri() { System.out.println("protected inner class:private"); } } class InnerClass { //访问权限修饰符修饰成员内部类的方法 void printInCDefDef() { System.out.println("default inner class:default"); } public void printInCDefPu() { System.out.println("default inner class:public"); } protected void printInCDefPro() { System.out.println("default inner class:protected"); } private void printInCDefPri() { System.out.println("default inner class:private"); } } private class InnerClassPri { void printInCPriDef() { System.out.println("private inner class:default"); } public void printInCPriPu() { System.out.println("private inner class:public"); } protected void printInCPriPro() { System.out.println("private inner class:protected"); } private void printInCPriPri() { System.out.println("private inner class:private"); } }
A.根据访问权限修饰符的特性,要验证每种成员内部类的访问权限,需要分别在
1).外部类
2).与外部类同一个包的类
3).与外部类不同包的子类
4).与外部类不同包的其他类
这4种类中添加测试代码。
注:
这里是把成员内部类当成外部类的一个成员来看的,即,成员内部类是一个整体,对其他类而言它就是外部类的一个变量而已,所以这里涉及到的子类是外部类的子类。
B.另,根据访问权限修饰符的特性,要验证每种成员方法的访问权限,需要分别在
1).外部类
2).与成员内部类同一个包的类
3).与成员内部类不同包的子类
4).与成员内部类不同包的其他类
1>.其他类是外部类的子类
2>.其他类不是外部类的子类
这5种类中添加测试代码。
注:
1].这里要测试的是成员内部类的成员方法,所以对情况3而言,应该是成员内部类的子类,而不是外部类的子类;
又由于成员内部类位于外部类的内部,所以其子类是不可能位于其他包中的,所以第3种情况是不存在的。
2].由于成员内部类是外部类的一个成员,其可见性对“与其不同包的”“外部类的子类和非子类”是不一样的,所以情况4要再细分成两种情况。
综合上面的A、B,下面几个图是所有的测试代码:
其中Person是外部类,TestMain是同包的类,GateMan是不同包的Person的非子类,Teacher是不同包的Person的子类。
由上图可知:
所有成员内部类对外部类都可见;
所有成员内部类的所有成员方法对外部类都可见;
由上图可知:
private修饰的成员内部类对与外部类同包的其他类是不可见的;
private修饰的成员内部类的所有成员方法对与内部类同包的其他类是不可见的;
public、protected及默认权限的成员内部类对与外部类同包的其他类是可见的;
public、protected及默认权限的成员内部类的public、protected及默认权限的成员方法对与内部类同包的其他类是可见的;
public、protected及默认权限的成员内部类的private权限的成员方法对与内部类同包的其他类是可见的;
由上图可知:
public修饰的成员内部类对与外部类不同包的非子类是可见的;
public修饰的成员内部类的public权限的成员方法对与内部类不同包的非子类是可见的;
public修饰的成员内部类的其他权限的成员方法对与内部类不同包的非子类是不可见的;
protected、默认及private修饰的成员内部类对与外部类不同包的非子类是不可见的;
protected、默认及private修饰的成员内部类的所有成员方法对与内部类不同包的非子类是不可见的---类不可见,其成员方法当然不可见;
注意28行,提示的错误与其他行都不一样:
即,protected修饰的成员内部类InnerClassPro的构造方法是不可见的。
但第42行,即inCPro.printInCProPu();是没有问题的,也就是说InnerClassPro是可以在Teacher里使用的。
为什么会出现这样的矛盾呢?
分析:
类Teacher与类Person不在同一个包里,但是其子类,所以protected修饰的内部类InnerClassPro对Teacher是可见的;
但类InnerClassPro没有显式创建构造方法,所以其默认的构造方法也是protected的;
对内部类InnerClassPro而言,类Teacher与其不在同一个包里,且不是其子类,所以,Teacher是看不到protected修饰的构造方法的;
因此就出现了上面的错误。
对策:
为类InnerClassPro添加构造方法,并声明为public的,这样就能保证Teacher能看到其构造方法并正确的创建InnerClassPro的对象了。
代码如下:
protected class InnerClassPro { //构造方法为public public InnerClassPro() { } ... }
修改后,就不会出现上面的问题了,见下图:
Teacher类里的完整测试代码如下,就不再一一分析了:
下图把16种情况的可见性依次列了出来,比较特殊的就是protected修饰的内部类InnerClassPro的public的成员方法,上面已详细解释说明过,不再赘述。(注:图有点大,可点开查看)