问题一: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. session放数据库里解决丢失的问题

    在编程里是会话的意思Session 对象存储特定用户会话所需的信息.这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去. ...

  2. java中如何使用Junit测试

    java中如何使用Junit测试 一.总结 一句话总结:a.单元测试的测试代码在test文件夹下,和源码不在同一个文件夹下 b.测试的类方法都以test开头,后面接要测试的类或者方法的名字 1.JUn ...

  3. sqlserver存储过程分页

    create  procedure [dbo].[SqlPager]@sqlstr nvarchar(4000), --查询字符串@currentpage int, --第N页@pagesize in ...

  4. 手写DCGAN

    //加上了注释,对pytorch又加深了理解import torch as t from torch import nn from torch.autograd import Variable fro ...

  5. Xcode8出现问题总结

    上点干货,目前得知的一些bug解决汇总:iOS10相册相机闪退bughttp://www.jianshu.com/p/5085430b029fiOS 10 因苹果健康导致闪退 crashhttp:// ...

  6. Meteor.js异步全解

    翻译来源: http://phucnguyen.info/blog/everything-you-need-to-know-about-async-meteor/ posted in Web Deve ...

  7. vue.js单个slot

    刚开始看这个slot的时候有点蒙,想了几分钟才明白过来,汗颜 <script> var mycompoent = Vue.extend({ template:"<div&g ...

  8. GPU Memory Usage占满而GPU-Util却为0的调试

    最近使用github上的一个开源项目训练基于CNN的翻译模型,使用THEANO_FLAGS='floatX=float32,device=gpu2,lib.cnmem=1' python run_nn ...

  9. selenium-java,暂停功能

    暂停/开始应用程序 public class Common_method { public void kill_chromedriver(){ Runtime runtime=Runtime.getR ...

  10. threejs通过射线Ray获取指定的点

    例:获取cube方向上的面的中点坐标(该cube默认方向为(0,1,0)) (中心点向cube quaternion 方向上发射射线,与正前方的面相交的点即为目标点; 由于ray只支持box和face ...