有这样的一段程序:
class Person {
int age = 0;
public Person() {
System.out.println("2、然后执行了super");
}
public void fun() {
System.out.println("super.age=" + age);
}
}
public class Test4 extends Person {
static {
System.out.println("1、先执行了static区域");
}
int age = 10;
public Test4() {
super.fun();
System.out.println("3、然后执行了this() age=" + age);
}
public Test4(int age) {
this();
System.out.println("4、然后执行了this(int age) 年龄是:" + age);
}
public static void main(String[] args) {
Test4 test = new Test4(20);
}
}
运行的结果如下:
1、先执行了static区域
2、然后执行了super
super.age=0
3、然后执行了this() age=10
4、然后执行了this(int age) 年龄是:20
有以上程序的运行结果我们不难发现java程序的执行步骤:对于static域的成员或static变量或static函数来说在JVM装载类的时候就已经为这些变量分配了实际的空间。在完成这些工作后,程序再去寻找函数main()的入口,执行main()中的代码块。
在这里顺便说一下栈空间和堆空间的区别:个人认为程序运行时它会申请一片空间,那么在程序中定义的变量在程序运行时都会占用这片空间中的一块,而堆空间是通过new关键字所产生的对象等所占用的空间。在该程序中,当使用new Test4(20)时程序便会首先执行该类中非静态变量的默认初始化,即在该程序中设a的初值为0;完成后然后看看构造函数中有没有传递形参过来,若有则先完成对其的赋值,即绑定构造方法的参数;然后检查构造函数中有没有this()或super()等形式的代码,若有则优先执行,于是在该程序中执行代码this();再跳转到另一个构造函数,这个构造函数执行与第一个构造函数一样的过程,于是先自动调用父类的构造函数执行其中的代码,然后再去对在类中定义的变量完成显示的初始化。一切工作完成后便会接着执行构造后数中那些真正属于它的代码段。