java类初始化中类成员的执行顺序解析

java类初始化中类成员的执行顺序解析

java初始化过程中,代码块,static代码块,实例成员变量,static变量,static方法和普通方法初始化顺序是怎样的呢?
首先看一段代码块,分析其输出打印结果

        public class App
        {
            private static App d = new App();
            private SubClass t = new SubClass();
            static
            {
                System.out.println(3);
            }
            {
                System.out.println(5);
            }
            {
                System.out.println(6);
            }
            public App()
            {
                System.out.println(4);
            }
            public static void main(String[] args)
            {
                System.out.println("hello");
            }
        }

        class SuperClass//父类
        {
            SuperClass()
            {
                System.out.println("构造器SuperClass");
            }
            static
            {
                System.out.println("superclass静态初始化");
            }
        }

        class SubClass extends SuperClass   //子类
        {
            static
            {
                System.out.println(1);
            }
            {
                System.out.println(7);
            }
            public SubClass()
            {
                //super();
                System.out.println(2);
            }
        }

打印出的答案为:

代码结果图1

为什么是这样的结果呢 ??

首先java中共有三种代码块:局部代码块,初始化代码块,静态初始化代码块
1.此题局部代码块不在我们考虑范围
2.初始化代码块(构造代码块):直接定义在类中
每次创建对象的时候都会先执行初始化代码块,通过反编译看到其本质是放到构造器中super()构造器后执行,优先于本类构造器代码先执行,完成初始化.
3.静态初始化代码块:使用static修饰的普通初始化代码块
所在类被加载时按顺序加载到的时候才执行初始化,优先于main方法执行
并且我们先记住3点
1.static修饰的变量和方法是随class的加载而加载并完成初始化的
2.static修饰的变量和方法是按照顺序加载的
3.实例变量是通过new调用构造器创建实例的时候才开始执行初始化的

好接下来我们来分析初始化过程:
1.首先第一步先加载第一个static语句,d声明后储存在方法区中,并调用构造器创建App实例
2.此时构造器会加载非静态变量
①.发现SubClass类型变量,先去包中寻找相关的类,找到SubClass后,再去找其父类SuperClass
②.找到SubClass所有关联类之后,先加载父类字节码文件,此时SuperClass(static代码块完成初始化,打印”superclass静态初始化”),然后再加载SubClass(加载时完成初始化,打印出”1”);
3.加载完关联类之后,调用SubClass构造器,SubClass构造器会默认先调用super()父类构造器输出(“构造器SuperClass”父类构造器总是在子类构造器第一行调用),
然后开始执行子类初始化代码段,其本质是在构造器中初始化,在父类构造器后执行,优先于子类构造器内容执行,输出代码“7”,然后执行子类构造器中代码输出”2”.
4.然后按顺序执行App构造器中初始化代码块,输出“5”“6”,然后执行构造器App()中代码,输出4;
5.实例变量加载完之后,按顺序加载static变量,此时开始加载static代码块,输出3.
6.在加载字节码文件最后执行main方法,输出”hello”
分析完成
最后,按照以上思路,大家分析一下下面代码的打印结果:

public class App 
{
    private static App d  = null;//stataic字段的初始化,
    {System.out.println("代码块啊");}
    private SubClass t = new SubClass();//非static字段的初始化其实都在构造器中,优先执行的.

    static
    {
        d = new App();
        System.out.println(3);
    }

    public App()
    {
        //t = new SubClass();
        //-----------------------------------
        System.out.println(4);
    }

    public static void main(String[] args)
    {
        System.out.println("Hello");
    }
}

//父类
class SuperClass
{
    SuperClass()
    {
        System.out.println("构造SuperClass");
    }
}

//子类
class SubClass extends SuperClass
{
    static
    {
        System.out.println(1);
    }

    SubClass()
    {
        //super();//表示调用父类无参数构造器
        System.out.println(2);
    }
}

运行结果为下图:

代码运行结果图
大家分析一下能否得到这个结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值