Java类加载的顺序-包含父子关系

                                                                         Java类加载的顺序-包含父子关系

首先看一段代码:

public class TestClassLoader {
    static class Father {
        public static final String TAG = "Father";

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

        {
            System.out.println("unStatic Father");
        }

        public Father() {
            System.out.println("constract Father");
            method();
        }

        public void method() {
            System.out.println("method Father");
        }

        @Override
        public String toString() {
            return "toString Father";
        }
    }

    static class Son extends Father {
        public static Son instance = new Son();

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

        {
            System.out.println("unStatic Son");
        }

        public Son() {
            System.out.println("constract Son");
            method();
        }

        public void method() {
            System.out.println("method Son");
        }

        @Override
        public String toString() {
            return "toString Son";
        }
    }

    public static void main(String[] args) {
//        System.out.println("1.---------------------");
//        System.out.println(Son.TAG);
//        Son[] sons = new Son[10];
//        System.out.println(sons);
//        System.out.println("2.---------------------");
        System.out.println(Son.instance);
//        System.out.println("3.---------------------");
//        Son son = new Son();
//        Father father = son;
//        father.method();
//        System.out.println(son);
    }
}

大家思考一下,上面代码执行以后的结果是什么样子的?

static Father
unStatic Father
constract Father
method Son
unStatic Son
constract Son
method Son
static Son
toString Son

我们会看到执行结果如上图所示。

那具体类加载的一个顺序到底是什么样子的呢?

1.首先静态代码块和静态变量肯定是要先进行加载的,并且同类里面的加载顺序是按代码顺序执行的

2.在调用构造方法的时候,会在构造方法之前,加载非静态代码块

3.最后才是调用类的构造方法

4.如果是父子关系,上面的每一步操作都需要先加载父类的相应方法

注意点:

1.静态代码块只会加载一次;

2.构造父类时,其所调用的静态成员和非静态属性是父类的,但是非静态的方法是子类的;

3.子类直接调用父类的静态变量,是不会加载子类的;

4.如果直接请求类的static final 修饰的变量(也就是在常量池中),类是不会被加载和初始化的;

那下面我们来针对于上面的代码进行分析;

我们执行 Son.instance 那程序会加载Son类,

 根据我们上面的第4条规则,由于Son类是有父类的,所以我们首先需要加载父类的静态代码块------打印 :static Father

然后执行子类的静态变量和静态代码块,根据第1条规则,同类静态加载按照代码顺序,此时我们会进行  new Son()

根据第1和第2条规则,我们首先会调用父类的非静态代码块-------打印:unStatic Father

然后执行父类构造方法,打印:constract Father

在父类构造方法中有调用非静态方法,根据注意点2,我们知道直接调用子类的方法,打印:method Son

父类构造完成之后,会按照1和2规则执行子类,会执行子类的非静态代码块,打印:unStatic Son

然后执行子类的构造,打印:constract Son

在子类构造中,调用自己的方法,打印:method Son

此时执行完了子类的第一步静态变量的加载,按照第1条规则,继续执行子类的静态方法,打印:static Son

到这里就完成了整个加载过程;

最后由于调用了  System.out.println  结果会执行子类的toString方法,打印:toString Son。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值