创建子类对象时父类子类中各代码的执行顺序

问题:

父类构造函数带有参数:
public Employee(int a ){}
子类要在构造函数中输入参数:

int a =1;
SE(){super(a);}

结果出错:
Cannot refer to an instance field arg while explicitly invoking a constructor(在明确调用一个构造器的时候不能引用类的一个实例域)
eclipse提示要将a变量加上static修饰符。
为什么成员变量就不行呢?

百度的解释

原因很简单,我们假如可以通过编译器。我问一个问题,调用构造器是干什么的?
大家都知道,创建一个对象并初始化对象中的数据域。红色字体很重要,在上面的列子中new MyThing()的作用就是为了初始化这个对象的数据域i,试问在没有通过构造器初始化之前,i的值是不确定的。我们怎么能使用一个不确定的i值来初始化对象。
必须要先明确初始化实例域,才能创建好对象,进而才能使用对象的数据域。在没有实例化之前就想使用他,不可能。

好像有点道理,但是又有了一个问题:
成员变量初始化是在执行构造函数之前,为什么已经int a =1了,super(a)中的a却没有确定的值?

答案:super()的调用先于成员变量初始化

经过断点调试后我发现了super()是在成员变量初始化之前执行的,所以执行时a还没有初始化。

执行过程

测试类,创建子类对象

public class Test {
    public static void main(String[] args) {
        SE se = new SE(5);
    }
}

子类

public class SE extends Employee{
    static String[] a = {"呵呵"};
    int b =4;
    static {
        System.out.println("子类静态代码块");
    }
    SE(){
        super(5);
        System.out.println("子类构造函数无参数");
    }
    SE(int a){
        this();
        System.out.println("子类构造函数");
    }

}

父类

public class Employee {
    static int id = 1;
    int abc  =50;
    public Employee() {
             super();
        System.out.println("父类构造函数无参数");
    }
    public Employee(int a ) {
        this();
        System.out.println("父类构造函数带参数");
    }
    static {
        System.out.println("父类静态代码块");
    }
}
开始执行:

1.加载SE的class文件
SE se = new SE(5);
2.直接进入父类初始化static类变量、static静态代码块
static int id = 1;
static {System.out.println("父类静态代码块");}
3.进入子类初始化类变量、静态代码块
static String[] a = {"呵呵"};
static {System.out.println("子类静态代码块");}
4.执行子类有参构造函数的this();
5.执行子类无参构造函数的super(5);
6.执行父类有参构造函数的this();
7.执行父类无参构造函数的super();
8.初始化父类的成员变量
int abc =50;
9.执行父类无参构造参数中的语句
System.out.println("父类构造函数无参数");
10.执行父类有参构造函数中的语句
System.out.println("父类构造函数带参数");
11.初始化子类的成员变量
12.执行子类无参构造参数中的语句
13.执行子类有参构造函数中的语句

结束。

总结

简单的来说就是
1.父类static模块
2.子类static模块
3.父类this()和super()
4.子类this()和super()
5.父类初始化成员变量,无参构造,有参构造
6.父类初始化成员变量,无参构造,有参构造

猜你喜欢

转载自www.cnblogs.com/john1998/p/static_super.html
今日推荐