一直对这个问题比较模糊,今天终于有时间来好好梳理下类的初始化顺序。
几个初始化的成分
静态:静态成员变量,静态代码块,静态成员方法。
非静态:非静态成员变量,非静态成员方法
构造代码块
举例说明:
class Insect {
private int i = 9;
protected int j;
//构造方法
Insect(){
System.out.println("父类构造函数"+"i="+i+",j="+j);
j = 39;
}
//静态成员变量
private static int x1= printInit("static insect .x1 initialized");
//静态方法1
static int printInit(String s){
System.out.println(s+"被调用的静态方法");
//p();
return 47;
}
//静态方法2
static void p(){
System.out.println("没有被调用的静态方法");
}
//静态代码块
static{
System.out.println("父类静态代码块");
}
//构造代码块
{
System.out.println("父类构造代码块");
}
}
public class Beetle extends Insect{
private int k = printInit("Beetle.k initialized");
public Beetle(){
System.out.println("子类构造函数"+"k="+k+",j="+j);
}
static{
System.out.println("子类静态代码块");
}
private static int x2 = printInit("static Beetle.x2 initialized");
public static void main(String args[]){
System.out.println("————————Beetle constructor—————分界线—————————————");
Beetle b = new Beetle();
}
{
System.out.println("子类构造代码块");
}
}
结果:
static insect .x1 initialized被调用的静态方法
父类静态代码块
子类静态代码块
static Beetle.x2 initialized被调用的静态方法
————————Beetle constructor—————分界线—————————————
父类构造代码块
父类构造函数i=9,j=0
Beetle.k initialized被调用的静态方法
子类构造代码块
子类构造函数k=47,j=39
结果说明:只是简单写了个程序来测试这些初始化的顺序。
静态代码块是在类加载的时候运行的,静态成员变量和静态方法的优先级按照其声明顺序,谁在前面谁的优先级高。构造代码块是在类进行实例化对象的时候运行的,构造代码块的执行要优先于构造方法。
子类父类之间,父类成员优先于子类成员,
静态非静态,静态要优先于非静态。
总结一下顺序:
父类中的静态成员变量和静态代码块
子类中的静态成员变量和静态代码块
父类的普通成员变量和代码块
父类的构造方法
子类的普通成员变量和代码块
子类的构造方法
举个例子:
class X{
Y y = new Y();
public X(){
System.out.println("X");
}
}
class Y{
public Y(){
System.out.println("Y");
}
}
public class Z extends X{
Y y = new Y();
public Z(){
System.out.println("Z");
}
public static void main(String args[]){
new Z();
}
}
结果:YXYZ
摘自牛客。
暂时只能想到这么多情况了,如果还有,后续再加。