java构造函数是否可继承,以及子类构造函数可否不使用super调用超类构造函数
问题一:java的构造函数能否被继承?
笔者初学java看的一本书说:“java的子类自然的继承其超类的“非private成员”。
通常java的构造函数被设置为public的(若你不写构造函数,java自动添加的无参空构造函数就是public的),因本文中的类都在同一个包中,因此使用无修饰的友好权限说明问题,对于private构造函数的意义,可参见这里。
那么根据该书所述规则,非private的构造函数当然也应该被子类继承。
但实际上,子类不仅无法继承private成员,也无法继承构造函数。
下面用代码进行说明。
示例1.
系统自动添加的无参空构造函数:(若不写构造函数,java默认添加一个无参的空构造函数)
- class base{
- }
- class derived extends base{
- public static void main(String[] args){
- derived d=new derived();
- }
- }
示例2.
把父类中系统自动添加的无参空构造函数显式的写出来(为了有输出,加了println):
- class base{
- base(){
- System.out.println("base constructor");
- }
- }
- class derived extends base{
- public static void main(String[] args){
- derived d=new derived();
- }
- }
输出结果:base constructor, 代码通过编译。从示例1,2来看,好像子类可以继承超类的构造函数哦。
但实际情况是:java规则:子类创建对象的同时会先创造父类的对象,因此必须先调用父类的构造方法。示例2中derived没有重写构造方法,根据java规则,系统会默认的添加一个无参的构造方法,且该方法第一句是super()。显式的写出来是:
- derived(){
- super();
- }
那为什么子类可以不写呢,因为:如果父类"只"有无参构造方法,且不打算重写子类的构造方法,为节省代码量,子类构造方法可以不写,系统默认调用父类无参构造方法super()。
可能还是有人觉得这些示例的说服力不够强,依然认为构造方法是可以继承的,没关系,看完本文,特别是示例4配合最后带★的文字,即可充分说明问题。
再来看看有参构造方法:
示例3.
如果将超类的构造方法改为有参构造方法,代码见下,则eclipse会报"Implicit super constructor xxx is undefined for default constructor. Must define an explicit constructor"
说明对于超类的有参构造方法,子类是无法继承的。
- class base{
- base(int x){
- System.out.println("base constructor,i="+x);
- }
- }
- class derived extends base{
- public static void main(String[] args){
- derived d=new derived();
- }
- }
对于有参的构造函数,子类中必须定义自己的构造方法。
(需要注意参数匹配,将该参数通过第一句的super(ParamList)传给父类的构造方法,若是多层继承,则需要逐级传递参数至最顶层的有参构造方法)
- class base{
- base(int x){
- System.out.println("base constructor,i="+x);
- }
- }
- class derived extends base{
- derived(int x){
- super(x); //这里使用了super(param),调用了超类的构造方法。
- System.out.println("derived constructor,i="+x);
- }
- public static void main(String[] args){
- derived d=new derived(8);
- }
- }
输出结果:
base constructor,i=8
derived constructor,i=8
问题二:子类的构造函数可否不使用super(ParamList)调用超类的构造方法?
上例中使用了super调用了超类的构造方法。同样是那本书中说:“子类的构造方法中必须使用super调用超类的构造方法,且super必须是子类构造方法的第一句。”
那我不用super行不行呢?原话给人的感觉好像是java的语法规定一样。
其实可以不用显式的写出super,但前提是“超类中有多个构造方法,且有一个是显式写出的无参的构造方法”。
示例4.
超类拥有多个构造方法,其中一个是显式的无参的构造方法。
- class base {
- base() { //warning_su
- System.out.println("base constructor."); //warning_su
- } //warning_su
- base(int x) {
- System.out.println("base constructor,i=" + x);
- }
- }
- class derived extends base {
- derived() { //warning_de
- System.out.println("derived constructor"); //warning_de
- } //warning_de
- derived(int x) {
- //super(x); //super被注释掉了!
- System.out.println("derived constructor,i=" + x);
- }
- public static void main(String[] args) {
- derived d= new derived(); //warning_cr
- derived t = new derived(8);
- }
- }
输出结果:
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调用超类构造函数的更多相关文章
- java学习之路--继承(子类构造器)
子类的构造器不能访问父类的私有域,所以必须用的父类的构造器来对这部分的私有域进行初始化,我们可以通过super实现对父类的构造器的调用,使用super调用父类构造器的语句,必须放在子类构造器的第一句. ...
- JAVA的覆盖、继承和多态的详细解说.this和super的用法
1. 继承: (1)子类的构造方法一定会调用父类的构造方法. (2)任何子类构造方法第一行肯定是this();或者super();两个择一. this();调用本类的其它构造方法.(传递相应参数调用相 ...
- 继承内部类时使用外部类对象.super()调用内部类的构造方法
问题简介 今天在看<Java编程思想>的时候,看到了一个很特殊的语法,懵逼了半天--一个派生类继承自一个内部类,想要创建这个派生类的对象,首先得创建其父类的对象,也就是这个内部类,而调 ...
- Java学习笔记之继承
一.继承的基础 在Java术语中,被继承的类叫超类(superclass)或者父类,继承超类的类叫子类(subclass). 举例说明: class Box { public double width ...
- c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放
看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...
- 子类A继承父类B, A a = new A(); 则父类B构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块 执行的先后顺序是
按照先后顺序: 1,静态先于非静态代码库执行(静态代码块随着类的加载而加载,初始化只执行一次) 2,父类先于子类 3,非静态代码块优于构造函数执行 所以执行顺序如下: 父类B静态代码块->子类A ...
- 继承:继承后子类构造函数具有隐式super,所以子类中所以的构造函数默认会访问父类中的空参数的构造函数
class Test { Test(){ System.out.println("Test"); } Test(String name){ System.out.println(& ...
- Java:【面向对象:类的定义,静态变量,成员变量,构造函数,封装与私有,this】
本文内容: 什么是面对对象 类的定义与对象实例化 成员变量 成员变量的有效范围 成员变量的赋值 静态变量.方法与实例变量.方法 构造函数 封装与私有 this关键字 注:函数和方法是一样东西.[由于我 ...
- 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数
上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...
随机推荐
- UOJ #185【ZJOI2016】 小星星
题目链接:小星星 首先有个暴力很好想.令\(f_{i,j,S}\)表示把\(i\)这棵子树对应到原图中的\(S\)集合,\(i\)号点对应到了\(j\)号点的方案数.这玩意儿复杂度是\(O(3^nn^ ...
- 【转】IntelliJ IDEA的光芒会盖过Eclipse吗
作为一个资深的Eclipse用户,我想对IntelliJ IDEA做一个更为严谨的审视.JetBrains的工作人员非常的友善,并为Podcastpedia.org和Codingpedia.org这两 ...
- 递归--练习3--noi7592求最大公约数问题
递归--练习3--noi7592求最大公约数问题 一.心得 两个低级错误:1. ll setMax(ll &m,ll &n)中无引用,结果只传值,没传地址2. return f(n,m ...
- POJ 3126 primepath bfs
题目链接:http://poj.org/problem?id=3126 题意:1维的坐标轴,给出起点和终点,求从起点到终点变换经历的最短的步数.起点,终点和中间变换的数字都是4位,而且都是质数. 思路 ...
- 两个Fragment之间传递数据
1.第一个Fragment BlankFragment blankFragment = new BlankFragment();Bundle bundle = new Bundle();bundle. ...
- Life Cycle(JSF+Facelets)
一.JSF Life Cycle: 图1 图2 应用程序的生命周期是指应用程序的各个阶段,从开始到结束.所有应用程序的生命周期.在web应用程序生命周期中,执行常见任务,包括以下内容.■处理传入的请求 ...
- 学习 Flask 扩展 Flask-RESTful
pip install Flask-RESTful Flask-RESTful扩展.首先,我们来安装上面这个扩展. from flask import Flask from flask_restful ...
- New Concept English Two 27 73
新概念一:对应小学水平,重在口语和基础.是不可多得的学习教材,全本144课,可以给孩子(hello world 级别的我)学半年.新概念二:对应高中水平,重在听力和场景对话,共96课,学后,听懂歪果仁 ...
- 如何优化tomcat配置优化
tomcat默认参数是为开发环境制定,而非适合生产环境,尤其是内存和线程的配置,默认都很低,容易成为性能瓶颈. tomcat内存优化 linux修改TOMCAT_HOME/bin/catalina.s ...
- LambdaMART简介——基于Ranklib源码(二 Regression Tree训练)
上一节中介绍了 $ \lambda $ 的计算,lambdaMART就以计算的每个doc的 $\lambda$ 值作为label,训练Regression Tree,并在最后对叶子节点上的样本 $la ...