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 ...
 
随机推荐
- Java Minor GC和FullGC
			
Minor GC触发条件:当Eden区满时,触发Minor GC. Full GC触发条件: 调用System.gc时,系统建议执行Full GC,但是不必然执行 老年代空间不足 方法去空间不足 通过 ...
 - 【Python】远离 Python 最差实践,避免挖坑
			
原文链接:http://blog.guoyb.com/2016/12/03/bad-py-style/ 最近在看一些陈年老系统,其中有一些不好的代码习惯遗留下来的坑:加上最近自己也写了一段烂代码导致服 ...
 - 【JMeter】 使用Synchronizing Timer设置请求集合点,实现绝对并发
			
布局设置说明 参数说明: Number of Simulated Users to Group 每次释放的线程数量.如果设置为0,等同于设置为线程租中的线程数量. Timeout in millise ...
 - Angular i18n
			
Angular2中使用ngx-translate进行国际化http://blog.csdn.net/u014291497/article/details/61233033 在 Angular 项目中添 ...
 - module.exports和exports
			
require 用来加载代码,而 exports 和 module.exports 则用来导出代码.但很多新手可能会迷惑于 exports 和 module.exports 的区别,为了更好的理解 e ...
 - gzip压缩初探
			
前言 我们平时工作中传文件时为了提高传输速度一般都会把文件压缩一下再传,那样速度回快一些,尤其是那些文件很多的文件夹,比较常用的压缩格式就是zip,rar了.那我们日常网页中利用http协议请求的那些 ...
 - VirtualBox使用物理硬盘建立磁盘
			
VirtualBox,只能用命令行来 建立磁盘才可以使用物理硬盘. 1.运行cmd,cd进入你的VirtualBox目录,如: cd C:\Program Files\Sun\VirtualBox ...
 - C++设计模式之中介者模式
			
中介者模式:用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互.中介者模式的例子很多,大到联合国安理会,小到房屋中介,都扮演了 ...
 - js固定表头的实现(转)
			
原文链接:http://www.th7.cn/web/js/201509/121055.shtml 参考链接:http://www.jb51.net/article/102568.htm 写两个表格, ...
 - Date、DateFormat、SimpleDateFormat、Calendar
			
package com.Date; import java.util.Date; /* * Date 表示特定的瞬间,精确到毫秒 * JDK1.0开始 * 构造方法(常用的方法,过时的不管): * D ...