父类如下:
package zzm.java.extendsDemo;
public class Parent {
/**
* 会报错,因为static按顺序进行加载的
*/
// static {
// System.out.println("i="+i);
// }
public static int i = 0;
{
i++;
System.out.println("i(非静态)="+i);
}
static {
i = i+1;
System.out.println("i(静态)="+i);
}
{
i++;
System.out.println("i(非静态)="+i);
}
public Parent(){
i++;
System.out.println("i(构造方法)="+i);
}
}
子类如下:
package zzm.java.extendsDemo;
public class Child extends Parent{
public static int i = 0;
{
i++;
System.out.println("i(子类非静态)="+i);
}
static {
i = i+1;
System.out.println("i(子类静态)="+i);
}
{
i++;
System.out.println("i(子类非静态)="+i);
}
public Child(){
//显示调用父类构造方法,必须放在最前面,和不写是一样的
super();
i++;
System.out.println("i(子类构造方法)="+i);
}
public static void main(String[] args) {
Child child1 = new Child();
Child child2 = new Child();
}
}
猜猜输出是啥?
下面是打印
i(静态)=1
i(子类静态)=1
i(非静态)=2
i(非静态)=3
i(构造方法)=4
i(子类非静态)=2
i(子类非静态)=3
i(子类构造方法)=4
i(非静态)=5
i(非静态)=6
i(构造方法)=7
i(子类非静态)=5
i(子类非静态)=6
i(子类构造方法)=7
由此我们得出下面几个结论:
1、先执行父类的静态变量、静态方法块,谁在前面谁先执行
2、在执行子类的静态变量、静态方法块,也是一样,谁在前面谁先执行
3、在执行父类的非静态变量、非静态方法块,接着执行对应子类
4、最后在执行父类构造方法、在执行子类构造方法
5、当类已经被加载后,第二次加载时不会在执行静态变量的赋值,已经静态方法块,但是会执行非静态变量的赋值和非静态方法块。
因为一个静态变量的初始化是在类加载的准备阶段,这个阶段会执行静态变量的赋值以及相关的静态代码块,是<client>()方法执行的,执行时机是类加载的时候
而非静态方法,是由<init>()方法执行的,执行时间是构造实例的时候,随着实例化时一起放在堆上