上篇文章--笔记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的成员方法,上面已详细解释说明过,不再赘述。(注:图有点大,可点开查看)

Java学习笔记21---内部类之对成员内部类的补充说明(二)的更多相关文章

  1. Java学习笔记20---内部类之对成员内部类的补充说明(一)

    上篇文章--笔记19简要介绍了成员内部类.局部内部类和匿名内部类,下面对成员内部类再补充一些内容. 主要有以下6点: 1.成员内部类不可以有静态成员,成员变量为static final时除外 2.外部 ...

  2. Java学习笔记之---内部类

    Java学习笔记之---内部类 (一)成员内部类 内部类在外部使用时,无法直接实例化,需要借助外部类信息才能实例化 内部类的访问修饰符可以任意,但是访问范围会受到影响 内部类可以直接访问外部类的成员, ...

  3. Java学习笔记19---内部类之简介成员内部类、局部内部类及匿名内部类

    内部类,顾名思义,即定义在某个类内部的类,称包含该内部类的类为外部类. 从定义的位置来说,分为成员内部类和局部内部类:从类的特征来说,分为匿名内部类和静态内部类. 今天先简要介绍一下前三种内部类的定义 ...

  4. Java学习笔记之——内部类

    内部类 形式:把一个类定义在一个类的内部. 分为:成员内部类和匿名内部类重点掌握 a) 成员内部类 b) 静态成员内部类 c) 匿名内部类 d) 局部内部类 (1)成员内部类: Java的语言是面向对 ...

  5. Java学习笔记:内部类/匿名内部类的全面介绍

    编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致:非public得,无强制要求).如果想把多个java类放在一 ...

  6. 3)Java学习笔记:内部类

    什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...

  7. 【原】Java学习笔记025 - 内部类

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 内部类(嵌套类): ...

  8. Java学习笔记21(String类补充:正则表达式)

    正如python的re模块,不过Java和Python的正则表达式有一些区别,这里做简单介绍,具体的细节可以参考网上其他的文章: 功能:可以用于检验一个字符串,比如验证用户名,验证密码格式,验证是否是 ...

  9. java学习笔记21(迭代器)

    java中有很多集合,内部有各种的存储的方法,取出的方法也各不相同,那么有没有一种通用的方法来取出来呢? java提供的遍历集合元素的方法有两种: 1.for-each结构(增强型for循环) 格式: ...

随机推荐

  1. 王磊:AI 时代物流行业的 OCR 应用

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ OCR 是人工智能里面非常重要的基础能力之一.腾讯云人工智能产品总监王磊,结合物流场景解读了OCR技术."OCR文本识别能够优化 ...

  2. 在PowerShell脚本中集成Microsoft Graph

    作者:陈希章 发表于2017年4月23日 我旗帜鲜明地表态,我很喜欢PowerShell,相比较于此前的Cmd Shell,它有一些重大的创新,例如基于.NET的类型系统,以及管道.模块的概念等等.那 ...

  3. 解决 ASP.NET Core MySql varchar 字符串截取(长度 255)

    ASP.NET Core 中使用 MySql,如果字段类型为varchar,不管设置多少长度,插入或更新数据的时候,会自动截断(截取 255 长度的字符). 出现问题的原因,就是使用了MySql.Da ...

  4. TP3.2.3 接入支付宝

    TP3.2.3 接入支付宝 项目接入支付宝支付了,在做这个给我的感觉是,方便 ,毕竟是老马的产品是吧, 话不多说 , 首先我们先找到官方的SDK  ,不想去找的小伙伴复制此链接 https://doc ...

  5. 「mysql优化专题」单表查询优化的一些小总结,非索引设计(3)

    单表查询优化:(关于索引,后面再开单章讲解) (0)可以先使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的.这可以帮我们分析是查询语句或是表结构的性能瓶颈. (1)写sql ...

  6. 5.python函数

    一.递归函数 如果一个函数在内部调用自身,那么这个函数就叫做递归函数. 1. 必须有一个明确的结束条件: 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少: 3.递归效率不高,递归层次过 ...

  7. 小白的Python之路 day2 文件操作

    文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 ...

  8. 【java】HashSet

    package com.tn.hashSet; public class Person { private int id; private String name; private String bi ...

  9. ES6之Symbol

    ES6中Symbol是为了防止属性名冲突而引入的,是独一无二的.Symbol值是通过Symbol函数生成.Symbol值不能与其他类型的值运算否则会报错且Symbol的值可以转换为字符串或者是布尔值但 ...

  10. Swift tableview自带的刷新控件

    import UIKit class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource { let ...