关于继承,大家肯定不会陌生,甚至经常使用。
在继承中有这么一条规定:子类无法继承父类的构造方法。
但是我们再看继承条件下的构造方法遵循以下几点规则:
规则一:如果子类的构造方法中没有通过super显式调用有参构造方法,也没用通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。
规则二:如果子类的构造方法中通过super显式调用父类相应的构造方法,那就不执行父类无参构造方法。
规则三:如果子类构造方法中通过this显式调用自身其他的构造方法,在相应构造方法中应用以上两条。
在这时我们如果在写父类时仅构造了一个有参的构造方法,而没有构造无参的构造方法,而在实例化子类时如果调用子类的无参构造方法,这时程序是不能通过编译的,如下:
首先看父类:
public class A {
public String name;
public A(String name){
this.name = name;
}
}
此时父类仅有一个有一个参数的构造方法。
然后看子类
public class B extends A {
public B(){
System.out.println("B");
}
}
此时子类仅有一个无参的构造方法,此时Eclipse中无法通过编译
然后看测试类
public class Test {
public static void main(String[] args) {
B b = new B();
}
}
运行此程序时将在控制台出现以下错误
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Implicit super constructor A() is undefined. Must explicitly invoke another constructor
at B.(B.java:3)
at Test.main(Test.java:4)
出现这个错误的原因就是上面说的规则一:如果子类的构造方法中没有通过super显式调用有参构造方法,也没用通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。
在子类构造方法中没有使用super关键字,也没有使用this关键字,这时系统会调用父类也就是A类的无参构造方法,但是此时A类中没有无参的构造方法,就会抛出这个异常。
那么上述三个规则就很容易理解了,下面看一个具体示例加深理解。
首先看有一个Person类,有name属性,同时有一个无参的构造方法,和一个有一个参数的构造方法。
public class Person {
String name;
public Person(){
System.out.println("执行人类的无参构造方法");
}
public Person(String name){
this.name = name;
System.out.println("执行人类有一个参数构造方法");
}
}
然后看学生类,它是人类的子类,有个school属性,和一个无参构造方法和全参构造方法
public class Student extends Person {
String school;
public Student(){
System.out.println("执行学生类的无参构造方法!");
}
public Student(String name,String school){
super(name);
this.school = school;
System.out.println("执行学生类全参构造方法");
}
}
然后看研究生类,它是学生类的子类,它有一个导师属性,和一个无参构造方法和一个全参构造方法。
public class Graduate extends Student {
String guide;
public Graduate(){
System.out.println("执行研究生类的无参构造方法");
}
public Graduate(String name,String school,String guide){
super(name, school);
this.guide = guide;
System.out.println("执行研究生类的全参构造方法");
}
}
然后看一下测试类
public class Test {
public static void main(String[] args) {
Graduate g = null;
g = new Graduate();
System.out.println();
g = new Graduate("张三", "北京大学", "李四");
}
}
代码分析:
首先在执行g = new Graduate();后,一共创建了四个对象,按照创建顺序依次是Object、Person、Student、Graduate对象。首先执行Graduate类的无参构造方法,这里没有使用super关键字也没有使用this关键字,这是根据规则一来看,这时会调用父类无参构造方法,Graduate类的父类是Student类;执行Student类的无参构造方法,Student的构造方法也没有使用super和this关键字,因此调用Student类的父类的无参构造方法,Student类的父类是Person类;执行Person类的无参构造方法也没有super和this关键字,这时继续调用Person类的父类的无参构造方法,Person类的父类是Object类,Object类的无参够方法没有做任何处理,这是生成一个Object对象,然后继续执行Person类无参构造方法中剩余部分,即在控制台打印输出执行人类的无参构造方法,然后生成一个Person类对象,然后继续执行Student类无参构造方法剩余部分…………
同时执行g=new Graduate("张三","北京大学","李四");会顺序执行父类的相应的构造方法,同时也是生成四个对象。
我们看一下执行结果截图: