Java学习笔记21---内部类之对成员内部类的补充说明(二)(修正)

修正:原文章有点错误,主要是关于成员内部类的子类的问题。

由于本人认知局限,想当然的认为内部类的子类也应该是内部类,其实不然,关于内部类的继承的知识点会在笔记22中说明。

改动的地方主要有:

1).追加了“ 5.InnerClassChild2与内部类不同包”,测试了内部类的成员方法在与成员内部类不同包的子类中的可见性。

2).修改了最后的图片,public的内部类的protected权限的成员方法的可见性为:同包的类及不同包的内部类的子类

 

上篇文章--笔记20补充说明了前四点,这里接着来说剩下的两点。

要点如下:

5.访问权限修饰符可以修饰成员内部类

    1).访问权限修饰符对内部类的访问限制与对外部类的一般成员遵循一样的规则,具体请参考笔记10

    2).这里涉及到的子类是外部类的子类

6.访问权限修饰符可以修饰成员内部类的成员变量和成员方法

    1).成员内部类可由4种访问权限修饰符修饰,每种内部类的成员方法或变量也可由4种访问权限修饰符修饰,所以分16种情况来讨论;

    2).修饰类时涉及到的子类是外部类的子类;修饰内部类的成员方法或变量时涉及到的子类是成员内部类的子类;

    3).构造方法的默认修饰符与类一致;

    4).在外部类的不同包子类中创建protected修饰的内部类的对象时,会提示构造方法不可见,这时要为该内部类添加public修饰的构造方法;

    5).内部类的成员方法的可见性,由内部类的修饰符及成员方法的修饰符共同决定

 

作者: 蝉蝉

请尊重作者劳动成果,如需转载请在标题注明“转载”字样,并标明原文链接:

http://www.cnblogs.com/chanchan/p/8337173.html

 PS:转成日记后怎么没办法转回随笔?只好重发一次了

 

下面详细展开说明。

类Person中定义了4个成员内部类,分别由public、protected、默认、private修饰;并给这4个成员内部类分别添加4个成员方法,分别由public、protected、默认及private修饰。代码如下:

 1     public class InnerClassPu {
 2         void printInCPuDef() {
 3             System.out.println("public inner class:default");
 4         }
 5         
 6         public void printInCPuPu() {
 7             System.out.println("public inner class:public");
 8         }
 9         
10         protected void printInCPuPro() {
11             System.out.println("public inner class:protected");
12         }
13         
14         private void printInCPuPri() {
15             System.out.println("public inner class:private");
16         }
17     }
18     
19     protected class InnerClassPro {
20         void printInCProDef() {
21             System.out.println("protected inner class:default");
22         }
23         
24         public void printInCProPu() {
25             System.out.println("protected inner class:public");
26         }
27         
28         protected void printInCProPro() {
29             System.out.println("protected inner class:protected");
30         }
31         
32         private void printInCProPri() {
33             System.out.println("protected inner class:private");
34         }
35     }
36 
37     class InnerClass {
38         //访问权限修饰符修饰内部类的方法
39         void printInCDefDef() {
40             System.out.println("default inner class:default");
41         }
42         
43         public void printInCDefPu() {
44             System.out.println("default inner class:public");
45         }
46         
47         protected void printInCDefPro() {
48             System.out.println("default inner class:protected");
49         }
50         
51         private void printInCDefPri() {
52             System.out.println("default inner class:private");
53         }
54     }
55 
56     private class InnerClassPri {
57         void printInCPriDef() {
58             System.out.println("private inner class:default");
59         }
60         
61         public void printInCPriPu() {
62             System.out.println("private inner class:public");
63         }
64         
65         protected void printInCPriPro() {
66             System.out.println("private inner class:protected");
67         }
68         
69         private void printInCPriPri() {
70             System.out.println("private inner class:private");
71         }
72     }

 

A.根据访问权限修饰符的特性,要验证每种成员内部类的访问权限,需要分别在

1).外部类

2).与外部类同一个包的类

3).与外部类不同包的子类

4).与外部类不同包的其他类

这4种类中添加测试代码。

注:

    这里是把成员内部类当成外部类的一个成员来看的,即,成员内部类是一个整体,对其他类而言它就是外部类的一个变量而已,所以这里涉及到的子类是外部类的子类。

 

B.另,根据访问权限修饰符的特性,要验证每种成员方法的访问权限,需要分别在

1).外部类

2).与成员内部类同一个包的类

3).与成员内部类不同包的成员内部类的子类(更正.2018.1.23)

4).与成员内部类不同包的其他类

    1>.其他类是外部类的子类

    2>.其他类不是外部类的子类

这5种类中添加测试代码。

注:

1].这里要测试的是成员内部类的成员方法,所以对情况3而言,应该是成员内部类的子类,而不是外部类的子类;

    又由于成员内部类位于外部类的内部,所以其子类是不可能位于其他包中的,所以第3种情况是不存在的。(这段话有误,成员内部类的子类可以位于其他包中 2018.1.24)

 2].由于成员内部类是外部类的一个成员,其可见性对“与其不同包的”“外部类的子类和非子类”是不一样的,所以情况4要再细分成两种情况。

 

综合上面的A、B,A中的1、2、3、4分别与B中的1、2、4.1、4.2范围一样,再追加B中3的测试代码即可,见下面第5条。(追加:2018.1.24)

下面几个图是所有的测试代码:

其中Person是外部类,TestMain是同包的类,GateMan是不同包的Person的非子类,Teacher是不同包的Person的子类。

 

1.Person内的测试:

 

由上图可知:

所有成员内部类对外部类都可见;

所有成员内部类的所有成员方法对外部类都可见;

 

2.TestMain内的测试:

由上图可知:

private修饰的成员内部类对与外部类同包的其他类是不可见的;

private修饰的成员内部类的所有成员方法对与内部类同包的其他类是不可见的;

public、protected及默认权限的成员内部类对与外部类同包的其他类是可见的;

public、protected及默认权限的成员内部类的public、protected及默认权限的成员方法对与内部类同包的其他类是可见的;

public、protected及默认权限的成员内部类的private权限的成员方法对与内部类同包的其他类是不可见的;

 

3.GateMan内的测试:

由上图可知:

public修饰的成员内部类对与外部类不同包的非子类是可见的;

public修饰的成员内部类的public权限的成员方法对与内部类不同包的非子类是可见的;

public修饰的成员内部类的其他权限的成员方法对与内部类不同包的非子类是不可见的;

protected、默认及private修饰的成员内部类对与外部类不同包的非子类是不可见的;

protected、默认及private修饰的成员内部类的所有成员方法对与内部类不同包的非子类是不可见的---类不可见,其成员方法当然不可见;

 

4.Teacher内的测试:

 

注意28行,提示的错误与其他行都不一样:

即,protected修饰的成员内部类InnerClassPro的构造方法是不可见的。

但第42行,即inCPro.printInCProPu();是没有问题的,也就是说InnerClassPro是可以在Teacher里使用的。

为什么会出现这样的矛盾呢?

 

分析:

    类Teacher与类Person不在同一个包里,但为Person的子类,所以protected修饰的内部类InnerClassPro对Teacher是可见的;

    但类InnerClassPro没有显式创建构造方法,所以其默认的构造方法也是protected的;

    对内部类InnerClassPro而言,类Teacher与其不在同一个包里,且不是其子类,所以,Teacher是看不到protected修饰的构造方法的;

因此就出现了上面的错误。

 

对策:

为类InnerClassPro添加构造方法,并声明为public的,这样就能保证Teacher能看到其构造方法并正确的创建InnerClassPro的对象了。

 

代码如下:

    protected class InnerClassPro {
        //构造方法为public
        public InnerClassPro() {

        }
         ...
    }

 

修改后,就不会出现上面的问题了,见下图:

 

 

Teacher类里的完整测试代码如下,就不再一一分析了:

 

 

5.InnerClassChild2与内部类不同包

InnerClassChild2要继承一个成员内部类,如下图所示,只有public修饰的成员内部类在其他包中可见,也就是说,只有public权限的成员内部类能在其他包中有子类。

 

InnerClassChild2继承了内部类Person.InnerClassPu, 如下图所示:

    创建子类对象inCCh,成员方法printInCPuPu和printInCPuPro都是可见的;由于InnerClassChild2是子类,且不同包,所以父类中由public和protected修饰的成员方法都是可见的,默认及private修饰的成员方法不可见;

    创建父类对象inCPu,只有成员方法printInCPuPu是可见的;

笔记10中也出现了这样的现象,下面的一段摘自笔记10:

如果在与Person不同包的子类Teacher中定义了Teacher类对象,则通过该对象可以访问和调用Person中public和protected修饰的成员变量和成员方法,default、private修饰的成员变量和成员方法都不可以访问或调用;

如果定义了Person类对象,则通过该对象只可以访问和调用Person中public修饰的成员变量和成员方法,protected、default、private修饰的成员变量和成员方法都不可以访问或调用。

疑问:不明白为什么会有这样的差异。

 

 

 总结:

通过上面的5步测试,可以看出:

    1).访问权限修饰符修饰成员内部类及成员内部类的成员时,与修饰一般类的成员时遵循一样的规则(见笔记10)。

    2).内部类的成员方法的可见性,由内部类的修饰符及成员方法的修饰符共同决定。

 

附:

下图把16种情况的可见性依次列了出来,比较特殊的就是:

    1).public修饰的内部类InnerClassPu  的  protected的成员方法;

    2).protected修饰的内部类InnerClassPro  的  public的成员方法;

原因上面已详细解释说明过,不再赘述。

(注:图有点大,可点开查看)

 

posted @ 2018-01-23 18:03  蝉蝉  阅读(346)  评论(0编辑  收藏  举报