每个类都会有自己的构造方法,即使没有写,在实例化时系统也会自动增加无参的的构造方法。那么问题就来了,如果子类继承父类,而每个类中都有不止一个的构造方法,那么系统使用这些构造方法的规则又是什么呢?总体说来有四点:
1 子类的构造过程中必须调用父类的构造方法
什么是构造方法,首先它是一个方法(I am joking here), 它是一个将class实例化成为一个对象的方法。所以说,任何class在实例化时都必须调用这个方法。 子类在实例化时必须首先实例化它的父类。因为子类的东西比父类多,在子类实例中会有一个父类对象,子类的实例通过super应用指向这个父类实例,在堆内存中会有子类自己的成员变量和整个一个父类。
如图,TestB 继承于TestA. TestB b = new TestB();
来看一个程序:
package test;
public class TestA {
private int value = 0;
public TestA(){
System.out.println("superclass()");
}//无参的构造方法,输出superclass()
public TestA(int i){
i = this.value;
System.out.println("superclass("+i+")");
}//有参的构造方法
}
package test2;
import test.TestA;
public class TestB extends TestA{
public TestB(){
System.out.println("subclass()");
}//在执行自己的构造方法之前,肯定要去找superclass的构造方法,默认为无参的
public static void main(String [] args){
TestB b = new TestB();
}
}
结果会输出 superclass()
subclass()
2 子类可以使用super(argument_list) 调用指定的父类构造方法
既然默认情况会调用父类的无参方法,那么如果我们想指定调用哪个呢? 用super(arguemnt_list) 而且必须放在子类构造方法的第一行。也就是说,首先构造父类,然后构造子类。没有爸爸,哪来的儿子?
问题又来了,我们都知道,在一个类中,如果我们不写构造函数,在实例化时系统自动指定无参构造方法,但是,一旦我们写了有参的构造方法,而没写无参的构造方法时,系统不再提供无参的构造方法。那么问题出现了,如果父类只有一个有参的构造方法,而在子类的构造方法中我们没用super调用父类的构造方法,系统还会还会默认盗用父类的无参构造方法吗?可是这是系统不是不为父类提供无参构造方法吗? 怎么办?(如果在父类中什么构造方法都不写,反而是没问题的)
package test;
public class TestA {
private int value = 0;
/**
public TestA(){
System.out.println("superclass()");
}
**/
public TestA(int i){
i = this.value;
System.out.println("superclass("+i+")");
}
}
package test2;
import test.TestA;
public class TestB extends TestA{
public TestB(){
System.out.println("subclass()");
}
public static void main(String [] args){
TestB b = new TestB();
}
}
总而言之,在父类中可以不写无参的构造方法,但是如果不写,那么就不写任何构造方法,也不会出错。如果只写有参构造方法,那么在它的子类的构造方法中一定要调用父类的有参构造方法。个人觉得最好在父类中写上无参的构造方法,然后在子类的构造方法中也要明确调用父类的构造方法。
3.继承中的重写
package tests;
class Base{
public Base(){
test();//since subclass overwritted it, us subclass's test() method
}
public void test(){
System.out.println("aaaaa");
}
}
class Sub extends Base{
private String name="";
public void test(){
System.out.println("as"+name.length());
}
}
public class Action {
public static void main(String[] args){
Sub s = new Sub();
}
}
当子类初始化时,首先构造一个父类,所以要调用父类的构造方法,因为在父类的构造方法中调用了test(), 而这个方法在子类中重写了,所以实际是调用了子类的test()方法,而此时,子类还没初始化,所以里面要用到name.length()出错。