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

问题:

父类构造函数带有参数:
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.父类初始化成员变量,无参构造,有参构造

posted @ 2019-12-05 17:39  最后的约翰  阅读(552)  评论(0)    收藏  举报