美文网首页
Java中类的加载顺序

Java中类的加载顺序

作者: BigDreamMaker | 来源:发表于2018-08-23 14:06 被阅读0次

    以前对类的加载顺序,静态变量的初始化,普通变量的初始化,构造函数的初始化,构造代码块,静态代码块的初始化顺序一直搞不清楚,于是乎今天特别的做了一下,记录。
    为了完成今天的测试,先给出测试类。

    1.测试类

    • 父类
    public class Father {
        
        static String staticVar1 = LoaderUtils.getMemberValue("[父类]静态变量1");
        static String staticVar2 = LoaderUtils.getMemberValue("[父类]静态变量2");
        
        String normalVar1 = LoaderUtils.getMemberValue("[父类]普通变量1");
        String normalVar2 = LoaderUtils.getMemberValue("[父类]普通变量2");
    
        {
            System.out.println("[父类]匿名构造函数初始化");
        }
        
        static {
            System.out.println("[父类]静态匿名构造函数初始化");
        }
    
        Father() {
            System.out.println("[父类]无参构造函数初始化");
        }
    
    }
    
    • 子类
    public class Son extends Father {
    
        static String staticVar1 = LoaderUtils.getMemberValue("[子类]静态变量1");
        static String staticVar2 = LoaderUtils.getMemberValue("[子类]静态变量2");
    
        String normalVar1 = LoaderUtils.getMemberValue("[子类]普通变量1");
        String normalVar2 = LoaderUtils.getMemberValue("[子类]普通变量2");
    
        {
            System.out.println("[子类]匿名构造函数初始化");
        }
    
        static {
            System.out.println("[子类]静态匿名构造函数初始化");
        }
    
        public Son() {
            System.out.println("[子类]无参构造函数初始化");
        }
    }
    
    • LoaderUtils:用于对静态,非静态成员变量进行赋值和控制台输出。
    public class LoaderUtils {
        public static String getMemberValue(String input) {
            System.out.println(input);
            return input;
        }
    }
    
    • 客户端
    public static void main(String[] args) {
            System.out.println("***************第[1]次调用构造函数**************");
            Son son1 = new Son();
            System.out.println("***************第[2]次调用构造函数**************");
            Son son2= new Son();
            System.out.println("***************第[3]次调用构造函数**************");
            Son son3 = new Son();
        }
    
    • 输出结果
    ***************第[1]次调用构造函数**************
    [父类]静态变量1
    [父类]静态变量2
    [父类]静态匿名构造函数初始化
    [子类]静态变量1
    [子类]静态变量2
    [子类]静态匿名构造函数初始化
    [父类]普通变量1
    [父类]普通变量2
    [父类]匿名构造函数初始化
    [父类]无参构造函数初始化
    [子类]普通变量1
    [子类]普通变量2
    [子类]匿名构造函数初始化
    [子类]无参构造函数初始化
    ***************第[2]次调用构造函数**************
    [父类]普通变量1
    [父类]普通变量2
    [父类]匿名构造函数初始化
    [父类]无参构造函数初始化
    [子类]普通变量1
    [子类]普通变量2
    [子类]匿名构造函数初始化
    [子类]无参构造函数初始化
    ***************第[3]次调用构造函数**************
    [父类]普通变量1
    [父类]普通变量2
    [父类]匿名构造函数初始化
    [父类]无参构造函数初始化
    [子类]普通变量1
    [子类]普通变量2
    [子类]匿名构造函数初始化
    [子类]无参构造函数初始化
    

    2.结果分析

    在本例中Son继承Father,并且在子,父类中分别定义了,静态变量,静态代码块,普通变量,构造代码块和构造函数。
    由结果可以看出,在第一次调用构造函数的过程中,虽然子类Son没有显示的调用父类的无参构造,但是Java会帮我们完成调用父类无参构造的过程。

    • 静态代码只会执行一次。
      从上面3次的输出结果可以看出,静态代码的初始化只有第一次new对象的时候会执行,之后再new对象则不再执行静态代码的初始化。
    • 静态优于非静态
      并且静态代码要优先于非静态代码先执行初始化。
    • 父类初始化先于子类初始化。
      在本例中,无论是静态还是非晶态资源的初始化,父类的初始化动作总是先于子类的初始化。
    • 初始化顺序和声明顺序相同
      无论是静态代码块,静态变量 。还是普通变量,构造代码块。他们的执行顺序和他们再类中的声明顺序有关,在前面的先执行,在后面的后执行。
    • 构造函数总是在最后执行。

    总结下来就是

    • 先静态后普通。
    • 先父类后子类。
    • 静态,非静态资源的初始化顺序等于其声明顺序。
    • 构造函数总在最后执行。

    相关文章

      网友评论

          本文标题:Java中类的加载顺序

          本文链接:https://www.haomeiwen.com/subject/dfgpiftx.html