继承内部类时使用外部类对象.super()调用内部类的构造方法
问题简介
今天在看《Java编程思想》的时候,看到了一个很特殊的语法,懵逼了半天——一个派生类继承自一个内部类,想要创建这个派生类的对象,首先得创建其父类的对象,也就是这个内部类,而调用内部类的构造方法创建其对象的语法,是外部类对象.super();
问题分析
我们都知道,在Java当中,当我们创建一个类的对象时,在构造方法的第一行会默认的调用父类的构造方法,创建一个父类的对象,并用super关键字引用父类的对象。所以若一个类,它继承了一个内部类,那我们创建这个类的对象前,当然也必须创建一个其父类的对象,也就是这个内部类的对象。
但是,麻烦的是,对于内部类来说,有一个规则,那就是每个内部类的对象,必定要绑定一个其外部类的对象,这就是在内部类中,能够调用外部类方法和操作外部类属性的原因。在我们平时创建内部类对象的时候,首先需要创建一个外部类对象,在使用 外部类对象.new 内部类() 语法来创建内部类对象,这时候内部类对象绑定的就是创建它的外部类对象。
所以,当我们有一个类,它继承自一个内部类的时,我们要创建它的对象,需要满足两个条件:
- 在创建对象前,要先创建好它的父类对象,也就是它继承的内部类对象;
- 想要创建内部类对象,你得先有这个内部类的外部类对象,以供他绑定;
于是出现了下面这种让人懵逼的代码:
代码案例
// 外部类
class Outer{
// 内部类
class Inner{
// 默认构造方法
Inner(){
}
// 带参构造方法
Inner(String string){
}
}
}
// 继承类内部类的类
public class Test01 extends Outer.Inner{
// 方式1:创建一个外部类Outer的对象,用来提供创建内部类所需的条件
private static Outer outer2 = new Outer();
// 方式2:类的构造方法传入一个外部类的对象,用来提供创建内部类所需的条件
public Test01(Outer outer1){
// 通过外部类对象.super()调用内部类的构造方法
outer1.super("调用Inner的带参数构造方法");
//也可以通过outer2调用
// outer2.super("调用Inner的带参数构造方法");
}
public static void main(String[] args) {
// 创建一个外部类的对象
Outer outer = new Outer();
// 创建内部类的派生类对象,传入外部类的引用
Test01 test01 = new Test01(outer);
}
}
代码解读
在上面的代码中我们可以看到,Test01继承了一个内部类,于是在它的构造函数中,我们需要给他提供一个外部类Outer的对象,使它在可以满足问题分析中所说的条件2。上面的代码使用了两种方式来提供外部类的对象:
- 将外部类对象作为构造方法的参数传递进来,也就是上面代码中的outer1;
- 为类创建一个静态的外部类成员,也就是上面代码中的outer2;
提供了外部类Outer的对象后,创建Test01的对象时,需要一同创建的父类对象(也就是Inner)就有了可以绑定的外部类对象。然而存在一个问题,平常我们创建一个子类的对象时,构造方法中第一行会自动调用父类的构造方法,不许要我们写,但是这里却不行。因为这里的父类是一个内部类,这也就意味着编译器并不知道你想用哪个外部类对象去创建这个内部类的对象,你需要自己指定内部类绑定的外部类对象。于是,就有了上面的代码:使用 外部类对象.super(参数) 调用内部类的构造函数,创建内部类的对象,且这个内部类对象绑定的外部类对象就是调用构造函数的内部类对象。
上面的代码中有两个外部类Outer的对象,使用哪个外部类对象,创建Test01对象时,一同创建的Inner对象绑定的就是哪个outer。除此之外,还有一个问题,若构造方法中有多行代码,那外部类.super语句一定得在第一行,这和创建普通类时super语句要在第一行类似。这也很好理解,因为父类的对象一定要在子类对象之前创建。
总结
总之最重要的就是记住,一个类继承了内部类时,在这个类中想要调用父类的构造方法,得使用**外部类对象.super(参数)语法,且必须显示的写出来,编译器不会自己帮你加,否则将无法成功创建类的对象。
参考文献
《Java编程思想》
继承内部类时使用外部类对象.super()调用内部类的构造方法的更多相关文章
- “全栈2019”Java第七十五章:内部类持有外部类对象
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 141、Java内部类之实例化外部类对象
01. 代码如下: package TIANPAN; class Outer { // 外部类 private static String msg = "Hello World !" ...
- 使用super调用父类的构造方法
package com.bjpowernode.t02inheritance.c09; /* * 使用super调用父类的构造方法 */public class TestSuper02 { publi ...
- java——多线程——内部类共享同一个外部类对象的成员变量
public class Shop { public static void main(String[] args) { Outer o=new Outer(); Thread t1=o.getSal ...
- Java内部类与外部类
错误提示: 没有任何类型 TestThread 的外层实例可访问.必须用类型 TestThread 的外层实例(例如,x.new A(),其中 x 是 TestThread 的实例)来限定分配. pu ...
- 深入理解Java中为什么内部类可以访问外部类的成员
内部类简介 虽然Java是一门相对比较简单的编程语言,但是对于初学者, 还是有很多东西感觉云里雾里, 理解的不是很清晰.内部类就是一个经常让初学者感到迷惑的特性. 即使现在我自认为Java学的不错了, ...
- java 内部类与外部类的区别
最近在看Java相关知识的时候发现Java中同时存在内部类以及非公有类概念,而且这两个类都可以不需要单独的文件编写,可以与其他类共用一个文件.现根据个人总结将两者的异同点总结如下,如有什么不当地方,欢 ...
- C++之内部类(内部类就是外部类的友元类,单向友元。只是内部类比友元类多了一点权限)
1. 内部类的概念 如果一个类定义在另一个类的内部,这个内部类就叫做内部类.注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类.外部类对内部类没有任何优越的访问权限. ...
- java内部类 和外部类的区别
java 内部类和静态内部类的区别 详细连接https://www.cnblogs.com/aademeng/articles/6192954.html 下面说一说内部类(Inner Class)和 ...
随机推荐
- Git 学习第二天(三)
删除文件: 先新建一个test文件到webgit版本库中,然后 git add git commit 当然,我们可以在文件夹中删除文件,git 也提供了命令 rm file 此时 ...
- python:Django 简介。
Django是基Python的重要WEB框架. 1.安装Django Web框架 安装 pip 安装 在命令行模式 执行 [pip install django == 2.0]或者 [pip in ...
- FP-Tree -关联规则挖掘算法(转载)
在关联规则挖掘领域最经典的算法法是Apriori,其致命的缺点是需要多次扫描事务数据库.于是人们提出了各种裁剪(prune)数据集的方法以减少I/O开支 支持度和置信度 严格地说Apriori和FP- ...
- js 中typeof 检测数据类型的时候需要注意的小细节
博客搬迁给你带来的不便,敬请谅解! http://www.suanliutudousi.com/2017/10/26/typeof-%E6%A3%80%E6%B5%8B%E6%95%B0%E6%8D% ...
- java-day18
函数式接口在java中指:有且仅有一个抽象方法的接口 @FunctionalInterface注解:可以检测接口是否是一个函数式接口 函数式接口的使用:一般可以作为方法的参数和返回值类型 自定义函数式 ...
- 连接分析算法-HITS-算法
转自http://blog.csdn.net/Androidlushangderen/article/details/43311943 参考资料:http://blog.csdn.net/hguisu ...
- Spark Streaming设计
- C/C++通用Makefile
最近的项目又回到了Linux上运行,这就需要在Linux下编译项目,写Makefile针对习惯了Windows的程序员来说是一件痛苦的事,如果有一个通用的Makefile该多好啊,本着这样的目的,我再 ...
- UartAssist串口调试工具
第一步安装UartAssist 第二步打开UartAssist 界面为 我们将我们的wifi模块连接电脑, 查看的端口号通过计算机管理设备管理器进行查看 根据要求发送数据 就可以了
- java.sql.Date和java.util.Date的联系和区别
1) java.sql.Date是java.util.Date的子类,是一个包装了毫秒值的瘦包装器,允许 JDBC 将毫秒值标识为 SQL DATE 值.毫秒值表示自 1970 年 1 月 1 日 0 ...