对象在实例化时都需要顺着调用其继承链上的每一个类的构造函数来完成构造,而且先执行父级的构造函数确保父类被实例化之后再执行子类的构造函数(超类的构造器在子类的构造器之前执行)。也就是说,如果你继承一个类,那么,在该类的构造函数中必须能调用父类的构造函数,否则编译不通过。如果在没有编写构造函数的情况下,其会调用默认的无参构造函数执行。
一般我们所说的不能子类化的类,除了final
类之外,还有就是构造器为私有的类,如:
public class A {
private A() { }
public void doSomeThing() {};
}
此时的A只定义了一个构造函数且其作用域为私有的,因此,其子类不能通过调用A的构造函数来实例化A
,所以这也是一个不能子类化的类。其通常应用于单例模式或工具类以及Builder模式()中。
当然,类A
也不是说绝对不能被子类化,对于能够访问其private
作用域的内部类来说,其是可以被内部类所子类化的,如下所示:
public class A {
private A() {}
// 可以被内部类子类化
class B extends A{}
static class C extends A{}
public void doSomeThing() {};
}
综上所述,如果要实例化一个类,则必须能够调用其继承链上的构造方法,如果要实现继承,那么则在子类中必须调用其父类的构造方法。
假设,我们有一个类B,只有一个带参的构造器,如下所示,那么,我们怎么继承类B呢?
public class B {
public B(String str) {...}
}
由于B自定义了构造方法了,所以系统不会自动生成无参构造器,所以,如果需要继承B,那么,其子类则必须显示的调用B的唯一构造方法B(String str),如下所示:
class C extends B{
public C(String str) {
// super方法必须在第一行调用,如果没有明确super方法的时候,其默认会调用无参的spuer()方法。
super(str);
}
}
如上所示,我们必须明确调用有参的super方法且必须在构造器的第一行调用,super关键字代表着父类,super方法代表调用父类的构造器,如果没有指定super方法,则会在第一行默认执行无参super()方法。如果上面的代码没有明确调用有参的super方法则会如下的编译器错误:Implicit super constructor B() is undefined for default constructor. Must define an explicit constructor