“全栈2019”Java第五十章:继承与构造方法详解

171 阅读8分钟
原文链接: www.toutiao.com

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

提示

本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。

1.构造方法

构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。

演示:

构造方法。

实现:

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

运行结果完全正确。

2.继承中的构造方法

子类从其父类继承所有成员(字段,方法和嵌套类)。构造方法不是成员,因此它们不是由子类继承的,但是可以从子类调用父类的构造方法。

演示:

子类Student继承自父类People,People类和Student类分别在各自的构造方法中显示输出一段话。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

从运行结果来看,最先显示输出的是父类People构造方法中语句,然后才是Student构造方法中的语句。

疑问一:父类的构造方法是否被调用过?

从运行结果来看,父类的构造方法一定被调用过。

疑问二:既然父类的构造方法被调用过,是在什么时候被调用的?

从运行结果来看,父类的构造方法被调用一定是在子类构造方法显示输出“Student构造方法”语句前被调用。

综述:事实上,在子类继承父类中,如果子类构造方法未显式调用父类构造方法,则Java编译器会自动插入对父类的无参数构造方法的调用。 如果父类没有无参数构造方法,则会出现编译时错误。 对象确实有这样的构造函数,因此如果Object是唯一的父类,则没有问题。

3.显式调用父类构造方法

根据上一小节的结论,我们知道子类继承父类时,如果不显式调用父类构造方法,则Java编译器会自动插入对父类的无参数构造方法的调用。请问我该如何显示调用父类构造方法呢?

显式调用父类构造方法格式:

“全栈2019”Java第五十章:继承与构造方法详解

演示:

显示调用父类构造方法。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

从运行结果来看和第一次我们隐式调用父类构造方法是一样的。这也说明了Java编译器确确实实自动地帮我们在子类构造方法的第一行插入了调用父类构造方法语句。

4.调用父类构造方法必须是子类构造方法中的第一行

重点:

调用父类构造方法必须是子类构造方法中的第一行。

演示:

调用父类构造方法不放在子类构造方法中的第一行。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

错误信息:

“全栈2019”Java第五十章:继承与构造方法详解

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(14, 14) java: 对super的调用必须是构造器中的第一个语句

上述错误中是这样描述的:“对super的调用必须是构造器中的第一个语句”,大家不要误会,“第一个语句”和“第一行”相比,“第一个语句”要比“第一行”描述更加准确,建议大家把两个描述都记住。其实,“第一行”这个说法流传更广一些。

解决上述错误,只需将super方法移至第一行即可。

5.需显式调用父类有参构造方法

假如父类中的构造方法只有一个,而且还有参数,那么子类必须得显式调用。

演示:

当父类构造方法只有一个,而且还有参数时,子类必须显式调用父类构造方法。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

运行结果没有问题。接下来,我们来试试去掉子类的super方法。

其他类无需修改。

修改Student类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

错误信息:

“全栈2019”Java第五十章:继承与构造方法详解

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(11, 22) java: 无法将类 lab.People中的构造器 People应用到给定类型; 需要: java.lang.String 找到: 没有参数 原因: 实际参数列表和形式参数列表长度不同

当我们子类没有显式调用父类构造方法时,Java编译器自动地为我们在子类构造方法的第一行插入super方法,而且调用的还是无参的构造方法。此时,我们父类People里面并没有一个无参的构造方法,只有一个有参的构造方法,所以调用失败。

疑问:“实际参数列表和形式参数列表长度不同”是什么意思?

实际参数列表指的是super方法传递的参数的个数。

形式参数列表指的是父类构造方法需要的参数的个数。

“全栈2019”Java第五十章:继承与构造方法详解

super()方法里面一个实际参数没传,而父类中的构造方法里面需要一个String类型的参数。所以,造成实际参数列表和形式参数列表长度不同。

6.当父类中有多个构造方法时,子类可任选其一调用即可

演示:

当父类中有多个构造方法时,子类可任选其一调用即可。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

从运行结果来看,准确无误。

当然了,你也可以写super(),还可以写super("tom")。

7.子类不可以在同一个构造方法中多次调用父类构造方法

演示:

子类构造方法中多次调用父类构造方法。

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

错误信息:

“全栈2019”Java第五十章:继承与构造方法详解

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 14) java: 对super的调用必须是构造器中的第一个语句Error:(14, 14) java: 对super的调用必须是构造器中的第一个语句

错误信息里面说的很清楚,对父类的构造方法调用语句必须在子类构造方法中的第一个语句。

8.构造方法调用链

如果子类构造方法显式或隐式地调用其父类的构造方法,我们可能会认为将调用一整个构造方法链,一直回到Object的构造方法。 事实上,情况就是这样。 它被称为构造方法调用链。

演示:

实现以下继承关系,并编写构造方法,在构造方法里面显示输出用以区分的语句。

“全栈2019”Java第五十章:继承与构造方法详解

实现:

People类:

“全栈2019”Java第五十章:继承与构造方法详解

Man类:

“全栈2019”Java第五十章:继承与构造方法详解

Student类:

“全栈2019”Java第五十章:继承与构造方法详解

Main类:

“全栈2019”Java第五十章:继承与构造方法详解

结果:

“全栈2019”Java第五十章:继承与构造方法详解

显示输出结果依次是People、Man、Student。其实People类上面还有一个父类Object,只不过它的构造方法里面什么都没写:

“全栈2019”Java第五十章:继承与构造方法详解

虽然它里面什么都没写,实际上也是调用了Object构造方法。因为People类里面构造方法的第一行也是调用super()方法。

总结

  • 子类从其父类继承所有成员(字段,方法和嵌套类)。构造方法不是成员,因此它们不是由子类继承的,但是可以从子类调用父类的构造方法。
  • 事实上,在子类继承父类中,如果子类构造方法未显式调用父类构造方法,则Java编译器会自动插入对父类的无参数构造方法的调用。 如果父类没有无参数构造方法,则会出现编译时错误。 对象确实有这样的构造函数,因此如果Object是唯一的父类,则没有问题。
  • 调用父类构造方法必须是子类构造方法中的第一行。
  • 当父类构造方法只有一个,而且还有参数时,子类必须显式调用父类构造方法。
  • 当父类中有多个构造方法时,子类可任选其一调用即可。
  • 如果子类构造方法显式或隐式地调用其父类的构造方法,我们可能会认为将调用一整个构造方法链,一直回到Object的构造方法。 事实上,情况就是这样。 它被称为构造方法调用链。

至此,Java中继承与构造方法相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java第四十九章:重载与重写对比详解

下一章

“全栈2019”Java第五十一章:继承与final关键字详解

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

“全栈2019”Java第五十章:继承与构造方法详解

版权声明

原创不易,未经允许不得转载!