java 静态代码块、静态变量、成员变量、构造代码块、构造方法的执行顺序

时间:2022-10-10 19:33:01

先给出几个用到的类。分析写在了注释里。

父类ClassA:

public class ClassA {  
    {  
        System.out.println("父类构造代码块1");  
    }  
      
    {  
        System.out.println("父类构造代码块2");  
    }  
    ClassB b = new ClassB();
    static   
    {  
        System.out.println("父类静态代码块1");  
    }  
      
    public ClassA() {  
        System.out.println("父类无参构造函数");  
    }  
      
    public ClassA(String str)  
    {  
        System.out.println("父类有参构造函数" + str);  
    }  
      
}  

ClassB:

public class ClassB {
ClassB(){
System.out.println("ClassB");
}
}

未继承ClassA的类:

/*
 * 最终总结:
 * 在非继承的情况下:
 * 先加载子类的(静态代码块、静态变量),接下来执行main函数,
 * 创建调用构造方法之前会先调用(构造代码块、成员变量)。括号中的,按代码先后顺序执行。
 * 且在【每次】调用某个类的构造方法之前,【都】一定会先(成员变量、构造代码块)。
 * 即:(静态代码块、静态变量)> (构造代码块、成员变量)> 构造方法。
 * ps:对于这中间用到(加载的)的其他类,同样遵循上述顺序。
 * */
public class ConstructorDemo{  
    
    private ClassA classTestA = new ClassA();  
      
    {  
        System.out.println("子类构造代码块1");  
    }  
      
    static   
    {  
        System.out.println("子类静态代码块1");  
    }  
    private static ClassA classTestB = new ClassA("classTestB");  
      
    {  
        System.out.println("子类构造代码块2");  
    }  
      
    static   
    {  
        System.out.println("子类静态代码块2");  
    }  
      
    public ConstructorDemo() {  
        System.out.println("子类无参构造函数");  
    }  
      
    public static void main(String[] args)  
    {  
        ConstructorDemo demo = new ConstructorDemo();  
    }  
  
}  

执行结果:

子类静态代码块1
父类静态代码块1
父类构造代码块1
父类构造代码块2
ClassB
父类有参构造函数classTestB
子类静态代码块2
父类构造代码块1
父类构造代码块2
ClassB
父类无参构造函数
子类构造代码块1
子类构造代码块2
子类无参构造函数

-------------------------------------------------------------------------------------------------------------------------------

继承父类ClassA的类:



public class ConstructorExtendDemo extends ClassA{  
 

   /*
     * 先加载静态文件,之后执行main方法,但是(成员变量、构造代码块)在构造方法之前执行。
     * 由ClassB的出现情况可以看出每一次执行该类的构造方法之前,都会先(成员变量、构造代码块)。
     * 
     * 最终总结:
     *在继承的情况下,会先加载父类静态代码块或者静态变量,然后加载子类中的静态代码块或者静态变量,
     *再接着执行main函数,创建对象时,先调用(成员变量、构造代码块),在调用构造方法。
     *但是main函数中的执行,在【每次】调用某个类的构造方法之前,【都】一定会先(成员变量、构造代码块)。
     *即:(静态代码块、静态变量)> (构造代码块、成员变量)> 构造方法。
     *注意,静态文件只加载一次!
     */  


public ConstructorExtendDemo(String str) {  
        super(str);  
        System.out.println("子类有参构造函数");  
    }  
    private ClassA classTestA = new ClassA();  
      
    {  
        System.out.println("子类构造代码块1");  
    }  
      
    static   
    {  
        System.out.println("子类静态代码块1");  
    }  
    private static ClassA classTestB = new ClassA("classTestB");  
      
    {  
        System.out.println("子类构造代码块2");  
    }  
      
    static   
    {  
        System.out.println("子类静态代码块2");  
    }  
      
    
      
    public static void main(String[] args)  
    {  
    ClassA a = new ClassA();
        ConstructorExtendDemo demo = new ConstructorExtendDemo("childClass");  
    }  
}  

执行结果:

父类静态代码块1
子类静态代码块1
父类构造代码块1
父类构造代码块2
ClassB
父类有参构造函数classTestB
子类静态代码块2
父类构造代码块1
父类构造代码块2
ClassB
父类无参构造函数
父类构造代码块1
父类构造代码块2
ClassB
父类有参构造函数childClass
父类构造代码块1
父类构造代码块2
ClassB
父类无参构造函数
子类构造代码块1
子类构造代码块2
子类有参构造函数