问题一:java的构造函数能否被继承?

笔者初学java看的一本书说:“java的子类自然的继承其超类的“非private成员”。

通常java的构造函数被设置为public的(若你不写构造函数,java自动添加的无参空构造函数就是public的),因本文中的类都在同一个包中,因此使用无修饰的友好权限说明问题,对于private构造函数的意义,可参见这里

那么根据该书所述规则,非private的构造函数当然也应该被子类继承。

但实际上,子类不仅无法继承private成员,也无法继承构造函数。

下面用代码进行说明。

示例1.

系统自动添加的无参空构造函数:(若不写构造函数,java默认添加一个无参的空构造函数)

  1. class base{
  2. }
  3. class derived extends base{
  4. public static void main(String[] args){
  5. derived d=new derived();
  6. }
  7. }

示例2.

把父类中系统自动添加的无参空构造函数显式的写出来(为了有输出,加了println):

  1. class base{
  2. base(){
  3. System.out.println("base constructor");
  4. }
  5. }
  6. class derived extends base{
  7. public static void main(String[] args){
  8. derived d=new derived();
  9. }
  10. }

输出结果:base constructor, 代码通过编译。从示例1,2来看,好像子类可以继承超类的构造函数哦。

但实际情况是:java规则:子类创建对象的同时会先创造父类的对象,因此必须先调用父类的构造方法。示例2中derived没有重写构造方法,根据java规则,系统会默认的添加一个无参的构造方法,且该方法第一句是super()。显式的写出来是:

  1. derived(){
  2. super();
  3. }

那为什么子类可以不写呢,因为:如果父类"只"有无参构造方法,且不打算重写子类的构造方法,为节省代码量,子类构造方法可以不写,系统默认调用父类无参构造方法super()。

可能还是有人觉得这些示例的说服力不够强,依然认为构造方法是可以继承的,没关系,看完本文,特别是示例4配合最后带★的文字,即可充分说明问题。

再来看看有参构造方法:

示例3.

如果将超类的构造方法改为有参构造方法,代码见下,则eclipse会报"Implicit super constructor xxx is undefined for default constructor. Must define an explicit constructor"

说明对于超类的有参构造方法,子类是无法继承的。

  1. class base{
  2. base(int x){
  3. System.out.println("base constructor,i="+x);
  4. }
  5. }
  6. class derived extends base{
  7. public static void main(String[] args){
  8. derived d=new derived();
  9. }
  10. }

对于有参的构造函数,子类中必须定义自己的构造方法。

(需要注意参数匹配,将该参数通过第一句的super(ParamList)传给父类的构造方法,若是多层继承,则需要逐级传递参数至最顶层的有参构造方法)

  1. class base{
  2. base(int x){
  3. System.out.println("base constructor,i="+x);
  4. }
  5. }
  6. class derived extends base{
  7. derived(int x){
  8. super(x);  //这里使用了super(param),调用了超类的构造方法。
  9. System.out.println("derived constructor,i="+x);
  10. }
  11. public static void main(String[] args){
  12. derived d=new derived(8);
  13. }
  14. }

输出结果:

base constructor,i=8

derived constructor,i=8

问题二:子类的构造函数可否不使用super(ParamList)调用超类的构造方法?

上例中使用了super调用了超类的构造方法。同样是那本书中说:“子类的构造方法中必须使用super调用超类的构造方法,且super必须是子类构造方法的第一句。”

那我不用super行不行呢?原话给人的感觉好像是java的语法规定一样。

其实可以不用显式的写出super,但前提是“超类中有多个构造方法,且有一个是显式写出的无参的构造方法”。

示例4.

超类拥有多个构造方法,其中一个是显式的无参的构造方法。

  1. class base {
  2. base() {                                          //warning_su
  3. System.out.println("base constructor.");  //warning_su
  4. }                                                 //warning_su
  5. base(int x) {
  6. System.out.println("base constructor,i=" + x);
  7. }
  8. }
  9. class derived extends base {
  10. derived() {                                        //warning_de
  11. System.out.println("derived constructor"); //warning_de
  12. }                                                  //warning_de
  13. derived(int x) {
  14. //super(x);                                //super被注释掉了!
  15. System.out.println("derived constructor,i=" + x);
  16. }
  17. public static void main(String[] args) {
  18. derived d= new derived();                       //warning_cr
  19. derived t = new derived(8);
  20. }
  21. }

输出结果:

base constructor.

derived constructor

base constructor.     <---------注意这里没有i=8哦。

derived constructor,i=8

此时,子类有参构造方法中没有使用super(x)调用超类的构造方法也通过编译了,但是不使用super(ParamList),new derived(8)调用的是超类的无参构造方法base()!

为什么要强调必须是“显式写出”的无参构造方法,您可以试试把带有warnning字样的代码注释掉(warning_su,warning_de,waring_cr3处),同时也注释掉super(x)。

因为此时超类和子类有构造方法(有参的那个),系统不会自动给超类添加无参的空构造函数,会造成子类找不到超类的无参构造方法super()来使用,同样会报"Implicit super constructor xxx is undefined for default constructor. Must define an explicit constructor"。

其实也说明了一个道理,即使我们不写super(),系统会自动的添加一句super(),此例中super()并不存在所以报错了。

当然,子类不调用超类的有参构造函数super(ParamList)的情况相对较少,所以那本书干脆说必须在第一句写上super(ParamList)。

★另外,如果单独注释掉子类中的无参构造函数derived()(不注释warning_su和warning_de),eclipse会说:"The constructor derived() is undefined"。

也证明了即使是无参构造函数,也是无法继承的。仅仅当超类中只有一个无参构造函数且不打算重写子类构造函数时,为节省工作量,子类构造函数可以不写,java在使用子类的构造函数时,自动添加一句super()来运行。

java构造函数是否可继承,以及子类构造函数可否不使用super调用超类构造函数的更多相关文章

  1. java学习之路--继承(子类构造器)

    子类的构造器不能访问父类的私有域,所以必须用的父类的构造器来对这部分的私有域进行初始化,我们可以通过super实现对父类的构造器的调用,使用super调用父类构造器的语句,必须放在子类构造器的第一句. ...

  2. JAVA的覆盖、继承和多态的详细解说.this和super的用法

    1. 继承: (1)子类的构造方法一定会调用父类的构造方法. (2)任何子类构造方法第一行肯定是this();或者super();两个择一. this();调用本类的其它构造方法.(传递相应参数调用相 ...

  3. 继承内部类时使用外部类对象.super()调用内部类的构造方法

    问题简介   今天在看<Java编程思想>的时候,看到了一个很特殊的语法,懵逼了半天--一个派生类继承自一个内部类,想要创建这个派生类的对象,首先得创建其父类的对象,也就是这个内部类,而调 ...

  4. Java学习笔记之继承

    一.继承的基础 在Java术语中,被继承的类叫超类(superclass)或者父类,继承超类的类叫子类(subclass). 举例说明: class Box { public double width ...

  5. c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放

    看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...

  6. 子类A继承父类B, A a = new A(); 则父类B构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块 执行的先后顺序是

    按照先后顺序: 1,静态先于非静态代码库执行(静态代码块随着类的加载而加载,初始化只执行一次) 2,父类先于子类 3,非静态代码块优于构造函数执行 所以执行顺序如下: 父类B静态代码块->子类A ...

  7. 继承:继承后子类构造函数具有隐式super,所以子类中所以的构造函数默认会访问父类中的空参数的构造函数

    class Test { Test(){ System.out.println("Test"); } Test(String name){ System.out.println(& ...

  8. Java:【面向对象:类的定义,静态变量,成员变量,构造函数,封装与私有,this】

    本文内容: 什么是面对对象 类的定义与对象实例化 成员变量 成员变量的有效范围 成员变量的赋值 静态变量.方法与实例变量.方法 构造函数 封装与私有 this关键字 注:函数和方法是一样东西.[由于我 ...

  9. 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数

     上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...

随机推荐

  1. Qt532_WebKit_SSL问题

    1.打开网页"http://www.baidu.com",它会跳转至"https://www.baidu.com/",使用 SSL了,于是 WebView 出现 ...

  2. 获取iframe(angular 动态页面)高度

    问题比较特殊,google了好久才得到启示 开发的angular页面,需要嵌入到客户的web页中,以iframe方式.由于iframe的高度需要指定,而angular动态生成机制导致页面高度会随时变化 ...

  3. Learn Rails5.2- ActiveRecord: Migration , spring的使用(不兼容的解决办法)

    偶然一次: 运行rails generate停止不动,网上查找答案,可能是bundle update 之后 spring 版本变化了,和正在运行的 spring 实例不兼容. Spring导致的同样的 ...

  4. 058——VUE中vue-router之实例操作新闻列表单页面应用与路由别名的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. centos6 Nginx+Tomcat负载均衡配置

    一.Nginx简介 Nginx是一个web服务器也可以用来做负载均衡及反向代理使用,目前使用最多的就是负载均衡,具体简介我就不介绍了百度一下有很多,下面直接进入安装步骤 二.Nginx安装 1.下载N ...

  6. Ethereum以太网搭建本地开放环境简明教程

    引言: 区块链技术的风起云涌预示着一个去中心化时代的来临,ethereum技术栈是目前业界最为应用广泛的基于区块链技术的技术方案,本文将记录如何基于本地环境来搭建私有区块链的开发环境. 部署私有区块链 ...

  7. windows 实用小工具(截图、进程管理)

    1. 截图 picpick:PicPick-NGWIN,一款全功能的设计工具,包含屏幕截图.图片编辑器.颜色选择器.像素标尺和其它更多的功能 2. 二进制/十六进制 十六进制(二进制)编辑器 3. p ...

  8. I.MX6 Android mmm convenient to use

    # # 主要是记录mmm的简便自动化执行方式,为了减少键盘输入 # ]; then echo echo " Usage: ./remmm.sh <source dirctory> ...

  9. HDU4819 Mosaic【树套树】

    LINK 题目大意 给你一个\(n*n\)矩阵,每个点有初始权值 q次询问每次把一个矩形的中心节点变成这个矩形中最大值和最小值的平均数 思路 很显然的树套树啊 就是一开始傻逼了没想到怎么去维护这个东西 ...

  10. Codeforces 148B: Escape

    题目链接:http://codeforces.com/problemset/problem/148/B 题意:公主从龙的洞穴中逃跑,公主的速度为vp,龙的速度为vd,在公主逃跑时间t时,龙发现公主逃跑 ...