类的加载顺序问题-demo展示

2023-12-31 23:40:27

? ? ? 面试的的时候经常会被问到包含静态代码块、实例代码块和构造器等代码结构的加载顺序问题,下面借用一个面试题,回顾一下类的代码加载顺序。

public class AooTest {

    public static void main(String[] args) {
        AooTest.f1();
    }
    
    static AooTest test1 = new AooTest();

    static {
        System.out.println("1");
    }

    {
        System.out.println("2");
    }

    AooTest() {
        System.out.println("3");
        System.out.println("a=" + a + ", b=" + b);
    }

    private static void f1() {
        AooTest aooTest = new AooTest();
        System.out.println("4");
    }

    int a = 5;
    static int b = 6;
}

先看一下输出结果:

2
3
a=5, b=0
1
2
3
a=5, b=6
4

? ? ? 这个题比较绕,一般就是面试的时候故意出的费脑细胞的题,开发的时候压根不会碰到。但是这种题能够加深我们对类加载机制的理解,现在我们逐行去分析一下:

1、首先执行main方法,这里会执行当前AooTest类的加载,引起类加载有7种情况:

??????1.1:创建类的实例,new关键词;
? ? ? 1.2:访问类或接口的静态变量,或者对静态变量赋值;
? ? ? 1.3:调用类的静态方法;
? ? ? 1.4:程序的启动类所在的类;
? ? ? 1.5:初始化一个类的子类时会引起父类的主动使用和初始化;
? ? ? 1.6:反射,如Class.forName("com.cn.Test01");
? ? ? 1.7:jdk1.7之后的动态语言支持也会引起类的初始化。

2、类的加载会出发静态代码块,这个题里面有多个静态属性和静态代码块,按照从上往下的顺序执行,依次是:

3、这里在执行1的时候,就去执行new AooTest(),对当前类实例化,那么实例化就需要执行成员属性赋值和实例代码块、之后再执行构造器,如果有多个成员属性或者多个实例代码块也是从上往下的顺序执行,这里我们看下:

所以,先输出 2(步骤1.1),之后对a赋值 a= 5(步骤1.2)。

然后再执行构造器的代码(步骤1.3),首先输出 3,接下来输出?a = 5, b=0,这里有些同学会有疑问,为什么 b 是0呢?大家注意看,前面类加载的时候,我们只是执行了步骤1,而 静态属性b的赋值要到步骤3种才能执行,所以这里b是没有被赋值的,默认是0。

4、然后回到前面的图,执行步骤2,输出1

5、再往下执行步骤3,注意这里b会被赋值了 b =6。

经过以上步骤,类的加载执行完成,所有的静态属性和静态代码块都执行完成。

6、下面进入了main方法,执行了 AooTest.f1()函数。

在f1方法里面,AooTest又一次被实例化了,所以如果前面被实例化的步骤一样,实例代码块输出2,构造器输出3,接下来输出输出?a = 5, b=6,这里注意,b在前面已经赋值了,所以与上面的输出不同。

7、实例化结束之后,最后输出 4?。

最后来总结一下类加载的顺序:

1、最先加载静态成员变量、静态代码块,如果有多个,按照从上往下的顺序加载;

2、其次实例化普通成员变量、实例代码块,如果有多个,按照从上往下的顺序执行;

3、最后执行构造器函数

文章来源:https://blog.csdn.net/qq_35850405/article/details/135320180
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。