成员内部类可以继承其他的类,也可以被其它类继承,本文主要说明其它类继承成员内部类的问题。

本文要点如下:

1).成员内部类的子类可以是内部类,也可以不是内部类;

2).当成员内部类的子类不是内部类或子类虽是内部类但与其父类不在同一个外部类时,子类的构造方法第一句要显式添加如下的语句:

外部类对象引用.super(参数);

这里的外部类指父类所在的外部类;

3).编译器默认给成员内部类的构造方法传入一个参数,该参数是内部类所依附的外部类对象的引用;

注:本文涉及到的类都是非静态类

作者: 蝉蝉

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

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

参考资料:

http://www.cnblogs.com/dolphin0520/p/3811445.html

背景知识点:

1).内部类是如何依附于外部类的?

编译器编译时,是把外部类与成员内部类编译成两个独立的文件的;

但会给成员内部类默认添加一个类型为外部类对象引用的成员变量并为构造方法默认传入一个类型为外部类对象引用的参数,并以该参数值来初始化该成员变量;

如下所示:

final Person this$0;

InnerClass(Person per){

    ...

    this$0 = per;

    ...

  }

也就是说,成员内部类的对象保存了一个外部类对象的引用,通过这个引用,内部类就可以无限制的访问外部类的成员了。

从这里也可以看出,创建成员内部类对象之前必须要存在一个外部类对象,即,成员内部类是依附于外部类的。

2).创建子类对象时,要先调用父类构造方法再调用子类构造方法。

详细参见笔记11

3).子类构造方法中如果没有显式调用super(参数),则会在构造方法最前面默认添加super();。

下面分三种情况来讨论:

1.子类是内部类且与父类位于同一个外部类

外部类是Person,父类是成员内部类InnerClassParent,子类是成员内部类InnerClassChild。

     //笔记22--成员内部类--父类
class InnerClassParent {
InnerClassParent (){
System.out.println("内部类--父类");
}
} //笔记22-成员内部类--子类
class InnerClassChild extends InnerClassParent {
InnerClassChild(){
System.out.println("内部类的子类是内部类且位于同一外部类");
}
} public static void main(String[] args) {
Person per22 = new Person();
InnerClassChild inCCh = per22.new InnerClassChild();
}

输出结果为:

内部类--父类
内部类的子类是内部类且位于同一外部类

分析:

  1).由背景知识点1)可知,编译后,

子类实际的样子大概是如下这样的:

     //笔记22-成员内部类--子类
class InnerClassChild extends InnerClassParent {
final Person this$0;

InnerClassChildIn(Person per){
super();
this$0 = per;
System.out.println("内部类的子类是内部类且位于同一外部类");
}
}

父类实际的样子大概是如下这样的:

     //笔记22--成员内部类--父类
class InnerClassParent {
final Person this$0;
InnerClassParent(Person per){
this$0 = per;
System.out.println("内部类--父类");
}
}

  2).根据上面的分析,作出执行的流程图,如下所示:

1>.先创建外部类对象per,再通过per来创建其成员内部类InnerClassChild(子类);

2>.要创建子类对象,必须先加载父类再加载子类(这里子类、父类都是初次使用,尚未加载),然后初始化父类成员并调用父类构造方法,最后再初始化子类成员并调用子类的构造方法;

3>调用完子类构造方法后,子类对象inCCh创建完成;

  3).子类对象inCCh创建后的内存结构图如下所示:

子类对象创建完成后,子类与父类都有一个外部类对象引用this$0,且都指向了per。

相关知识点:

1>.堆、栈,参见笔记把大端、小端与堆、栈的生长方向联系起来记忆

2>.隐藏与覆盖,参见笔记12

2.子类是内部类且与父类位于不同的外部类

外部类DustMan的成员内部类是InnerClassChildDM,InnerClassChildDM继承了外部类Person的成员内部类InnerClassParent。

子类InnerClassChildDM的代码如下:

     //笔记22--成员内部类--子类为内部类且不在同一个外部类
class InnerClassChildDM extends Person.InnerClassParent {
InnerClassChildDM(Person per){
per.super();
System.out.println("成员内部类的子类为内部类且与父类不在同一个外部类");
}
}
public static void main(String[] args) {
DustMan du = new DustMan();
Person per = new Person();
InnerClassChildDM inCChDM = du.new InnerClassChildDM(per);
}

输出结果如下:

内部类--父类
成员内部类的子类为内部类且与父类不在同一个外部类

分析:

    1).编译后,子类的实际样子大概是下面这样的:

     //笔记22--成员内部类--子类为内部类且不在同一个外部类
class InnerClassChildDM extends Person.InnerClassParent {
final DustMan this$0;
InnerClassChildDM(DustMan du, Person per){
per.super();
this$0 = du;
System.out.println("成员内部类的子类为内部类且与父类不在同一个外部类");
}
}

    2).与第一种情况不同的是,子类InnerClassChildDM中显式添加了per.super();

这是因为,子类与父类处于不同的外部类,编译时,子类的构造方法默认传入的是DustMan类的对象引用,而不是Person类的对象引用;

如果要调用父类的构造方法的话,必须要给它传入一个其外部类Person的对象引用;

所以这时,子类的构造方法显式传入一个Person类对象引用per,并通过per.super();的方式把per传给父类的构造方法并调用之。

    3).执行的流程图如下所示:

    4).子类对象inCChDM创建完成后的内存分配图如下:

其中,子类的this$0是指向DustMan类的对象du的,父类的this$0是指向Person类的对象per的。

3.子类不是内部类

InnerClassChild不是内部类,它继承了外部类Person的成员内部类InnerClassParent。

 package human;

 public class InnerClassChild extends Person.InnerClassParent {
InnerClassChild(Person per) {
per.super();
System.out.println("内部类的子类不是内部类");
} public static void main( String[] args ) {
Person per = new Person();
InnerClassChild inCCh = new InnerClassChild(per);
}
}

输出结果如下:

内部类--父类
内部类的子类不是内部类

分析:

    1).子类不是内部类,所以编译器不会在其构造方法中传入其外部类的对象引用。

    2).子类的构造方法也显式的添加了per.super();语句,原因同上。

    3).执行的流程图如下所示:

    4).子类对象inCChNoI创建完成后,内存分配图如下:

其中,只有父类有this$0成员变量,且指向了Person类的对象per。

总结:

成员内部类的非静态子类可以是与其位于同一个外部类的子类,也可以是位于不同外部类的子类,还可以是一般类。

后两种情况,必须在子类的构造方法中显式添加 父类的外部类的对象.super(参数); 这样一条语句,以保证为父类传入其外部类的对象引用,继而保证能调用父类的构造方法。

Java学习笔记22---内部类之成员内部类的继承问题的更多相关文章

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

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

  2. 疯狂java学习笔记之面向对象(五) - 封装、继承、多态

    一.封装: 封装的概念: - 合理的隐藏:隐藏不想被外界操作的Field.方法.构造器 - 合理的暴露:一般就是希望给别人调用的方法 e.g:显示器(按键暴露出来操作,但实际的东西/细节方法被隐藏起来 ...

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

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

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

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

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

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

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

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

  7. Java学习笔记22(Date类、DateFormat类)

    Date,时间和日期类,这里讲util包中的而不是sql包中的 Date:表示特定的时间瞬间,精确到毫秒(1000毫秒=1秒) 时间和日期的操作都基于毫秒值 时间原点:1970年1月1日,0时0分0秒 ...

  8. Java学习笔记22(List接口)

    List接口继承自Collection接口,自身具有三大特点: 1.有序集合:存入和取出的顺序一致: 2.此接口的用户可以对每个元素插入位置进行精确控制:可以通过索引操作元素 3.可以存储重复元素 L ...

  9. Java学习笔记(三)——封装、继承、多态

    一.封装 概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 实现步骤: 修改属性的可见性——设为private. 创建getter/se ...

随机推荐

  1. requests爬取网页的通用框架

    概述 代码编写完成时间:2017.12.28 写文章时间:2017.12.29 看完中国大学MOOC上的爬虫教程后,觉得自己之前的学习完全是野蛮生长,决定把之前学的东西再梳理一遍,主要是觉得自己写的程 ...

  2. 初学者福音——10个最佳APP开发入门在线学习网站

    根据Payscale的调查显示,现在的APP开发人员的年薪达到:$66,851.这也是为什么那么多初学的开发都想跻身到APP开发这行业的主要原因之一.每当你打开App Store时候,看着琳琅满目的A ...

  3. Django2文档-入门概览

    Django 概览 Django 是设计是为了使通用的Web开发任务变得快速而又简单, 一下是如何使用Django编写数据库驱动的Web应用程序的非正式概述. 这个文档的目标是给你足够的技术细节来理解 ...

  4. java 实现的c当中的几道题

    package javastudy; /* * 利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示, 60分以下的用C表示. */ import jav ...

  5. jamup与gb2i组合

    软件一定要开嗓单效果器,最好不要关闭中断软件/声音,每次有重新检测电流必须会有嗓音,最好用ipad ,不然会烦死人.默认delay太长,在DLY面板修改 gb2i 效果还行,他的价值重在使用,让新人使 ...

  6. Python 项目实践三(Web应用程序)第五篇

    接着上节继续学习,在这一节,我们将建立一个用户注册和身份验证系统,让用户能够注册账户,进而登录和注销.我们将创建一个新的应用程序,其中包含与处理用户账户相关的所有功能.我们还将对模型Topic稍做修改 ...

  7. 小白的Python之路 day5 python模块详解及import本质

    一.定义 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test) 包:用来从逻辑上组织模块 ...

  8. linux下搜索指定内容

    echo " ls *.$2 | while read file;do out=$( (grep -n $1 $file) ) [ -n \"$out\" ] & ...

  9. element-ui+vuex共享自定义方法进行表单验证 validator

    element-ui的官网上写的自定义表单验证,方法都是写在单vue文件中的,不容易共享.怎么使用vuex将方法共享出来,各个组件都能用呢? 如下是一个验证age的数据, rules:{ age:[{ ...

  10. vue2.0 配置sass

    一.配置sass依赖 npm install node-sass --save-dev npm install sass-loader --save-dev 二.打开build文件夹下的webpack ...