下面我将通过一个例子来让你明白java中new一个对象的执行流程
public class Father{
private int i = test();
private static int j = method();
static{
System.out.print("(1)");
}
Father(){
System.out.print("(2)");
}
{
System.out.print("(3)");
}
public int test(){
System.out.print( "(4)");
return 1;
}
public static int method(){
System.out.print("(5)");
return 1;
}
}
public class Son extends Father{
private int i= test();
private static int j = method();
static{
System.out.print( "(6)");
}
Son(){
System.out.print("(7)");
}
{
System.out.print( "(8)");
}
public int test(){
System.out.print("(9)");return 1;
}
public static int method() {
System.out.print("(10)");
return 1;
}
public static void main (String[]args){
Son s1 = new Son();
System.out.println();
Son s2 = new Son();
}
}
这个例子的执行结果是:
Son继承与Father,所以在类加载的时候会先加载父类,然后再加载子类
static 关键字会在类加载的时候执行,究竟应该先执行static修饰的属性还是static修饰的代码块?
答:谁在前,就先执行谁,我们这个例子是static修饰的属性在前,因此先执行的是static修饰的属性。所以有了(5)(1)的输出
父类加载完毕就要开始加载子类,加载子类就得去加载子类修饰的静态方法。所以这时有(10)(6)的输出。
上面的步骤执行完毕,就要开始执行 构造器 的方法了。
这个地方需要注意,子类的执行自己的空参构造器前,默认首先要调用super()方法,也就是执行父类的空参构造器。
但是执行父类的空参构造器前,又会初始化父类的属性和代码块,具体要先初始化父类的属性还是代码块要看属性和代码块谁先写在前面,我们这里是属性写在前面,所以先执行父类的private int i = test();但是test()方法又被子类进行了重写,所以这里输出了(9),然后接着执行父类的代码块内容输出(3),然后执行父类的空参构造器输出(2),Father执行完了,也就是super()方法执行完毕,这个时候就该执行子类的空参构造器,但是执行构造器之前跟执行父类空参构造器一样,会先初始化它的属性和代码块,也是就执行Son的test方法,此时输出(9),然后是代码块的内容(8),最后便是构造器的代码输出(7)。
第一个new Son()的结果解释如上。
当我们再一次new Son()的时候,jvm类加载只会加载一次,不会重复加载,所以把第一次属于类加载的输出(5)(1)(10)(6)去掉便得到第二次结果的输出。