简单谈一下Java程序设计语言中,子类构造器与其父类构造器的关系。
Java是属于单继承的对象语言,子类可以继承并且使用其父类的所有变量和方法,非常典型的例子是Java中所有类都是继承于超级类Object,因此每一个类都可以使用Object类中的变量和方法。子类在继承父类时需要extends标记继承的父类,例如public class sun extends father{},其中子类sun继承了父类father。然而,有时候你会发现,在子类的构造器中没用使用super()调用其父类相应的构造器时,会出现错误无法编译,而有的时候又不需要在子类构造器中使用super()调用父类相应的构造器,为什么嘞?可以来研究一下。
什么时候需要使用super()调用父类的构造器,仔细分析起来可以有多种情况,但是我们只要看到调用的本质就能很容易判断什么时候需要调用父类的构造器以及怎么调用。 上面提到,Java中的子类可以使用父类的所有变量和方法,因此子类都可以往上强制转换为父类的对象类型,但是转换后的对象不能使用子类中相对于父类特有的东西。我们可以从这个现象中发现一点东西,我们可以这么理解为子类就是在实现父类的基础上,再加上子类本身特有的一点变量和方法,也就是说子类=父类+新增的变量+新增的方法。对象语言的构造器作用在于对类创建实例对象时完成对象的初始化工作(为变量申请内存空间等),因此,子类的构造器除了承担着初始化子类的新增变量和方法,还要初始化父类自身新增加的变量和方法。一般来说,如果在子类的构造器中没有使用super()调用父类相应的构造器,子类的构造器会自动调用父类默认的,也就是不带参数的构造器来初始化父类的东西。这里又要谈到Java类的默认构造器,当你没有为你写的类建造构造器的时候,Java会自动帮你创建这个默认构造器,但是当你自己编写了构造器后,你自己编写构造器将会覆盖掉默认的构造器,就是说默认的构造器不存在。那么这个时候,你在继承的子类里面没有显示添加super()函数调用你在父类里编写的父类构造器,子类的构造器将不能自动找到父类的构造器。找不到父类的构造器意味着什么?意味着你的子类实例化的时候找不到父类的构造器来初始化父类的东西,不能完成类实例对象的初始化工作,你说你的子类能不出现错误?!
所以,在子类的构造器中需不需要添加super()调用父类相应的构造器,只需要考虑子类的构造器才初始化的时候能不能完成所有变量和方法的初始化就可以了。另外,根据自己初始化工作的需要使用super()调用相应的父类构造器来初始化也是有必要的。
Java是属于单继承的对象语言,子类可以继承并且使用其父类的所有变量和方法,非常典型的例子是Java中所有类都是继承于超级类Object,因此每一个类都可以使用Object类中的变量和方法。子类在继承父类时需要extends标记继承的父类,例如public class sun extends father{},其中子类sun继承了父类father。然而,有时候你会发现,在子类的构造器中没用使用super()调用其父类相应的构造器时,会出现错误无法编译,而有的时候又不需要在子类构造器中使用super()调用父类相应的构造器,为什么嘞?可以来研究一下。
什么时候需要使用super()调用父类的构造器,仔细分析起来可以有多种情况,但是我们只要看到调用的本质就能很容易判断什么时候需要调用父类的构造器以及怎么调用。 上面提到,Java中的子类可以使用父类的所有变量和方法,因此子类都可以往上强制转换为父类的对象类型,但是转换后的对象不能使用子类中相对于父类特有的东西。我们可以从这个现象中发现一点东西,我们可以这么理解为子类就是在实现父类的基础上,再加上子类本身特有的一点变量和方法,也就是说子类=父类+新增的变量+新增的方法。对象语言的构造器作用在于对类创建实例对象时完成对象的初始化工作(为变量申请内存空间等),因此,子类的构造器除了承担着初始化子类的新增变量和方法,还要初始化父类自身新增加的变量和方法。一般来说,如果在子类的构造器中没有使用super()调用父类相应的构造器,子类的构造器会自动调用父类默认的,也就是不带参数的构造器来初始化父类的东西。这里又要谈到Java类的默认构造器,当你没有为你写的类建造构造器的时候,Java会自动帮你创建这个默认构造器,但是当你自己编写了构造器后,你自己编写构造器将会覆盖掉默认的构造器,就是说默认的构造器不存在。那么这个时候,你在继承的子类里面没有显示添加super()函数调用你在父类里编写的父类构造器,子类的构造器将不能自动找到父类的构造器。找不到父类的构造器意味着什么?意味着你的子类实例化的时候找不到父类的构造器来初始化父类的东西,不能完成类实例对象的初始化工作,你说你的子类能不出现错误?!
所以,在子类的构造器中需不需要添加super()调用父类相应的构造器,只需要考虑子类的构造器才初始化的时候能不能完成所有变量和方法的初始化就可以了。另外,根据自己初始化工作的需要使用super()调用相应的父类构造器来初始化也是有必要的。