(三)JAVA基础及提高篇父类、子类的加载顺序

  • Post author:
  • Post category:java

父类、子类的加载顺序

       1、父类的静态变量和静态块赋值(按照声明顺序)
  2、自身的静态变量和静态块赋值(按照声明顺序)
  3、父类的成员变量和块赋值(按照声明顺序)
  4、父类构造器赋值
  5、自身成员变量和块赋值(按照声明顺序)
  6、自身构造器赋值
  7、静态方法,实例方法只有在调用的时候才会去执行

特别注意:当静态加载中遇到需要加载非静态的情况: 先加载非静态再加载静态(因为非静态可以访问静态,而静态不能访问非静态)

demo说明,结构图如下:

入口Client类

package com.other;

import org.junit.Test;

/**
 *1、牢记:静态和非静态分开处理
 *  (1)使用到静态加载时,静态又分为: 静态变量, 静态代码块,其中加载顺序是按照类中书写的先后顺序加载的
 *  (2)非静态加载顺序: 按照非静态书写顺序加载执行
 *  (3)静态方法,实例方法只有在调用的时候才会去执行
 *  (4)当静态加载中遇到需要加载非静态的情况: 先加载非静态再加载静态(因为非静态可以访问静态,而静态不能访问非静态)
 *
 * 2、静态变量声明一定放在静态块使用前面
 *
 * 3、入口test方法虽然是一个特殊的静态方法,但是还是静态方法,此时JVM会加载test方法所在的类,试图找到类中其他静态部分
 */
public class Client {
    @Test
    public void test(){
        System.out.println("---new A() Begin---");
        A a1 = new A();
        System.out.println("---new A() end---\n");
        System.out.println("---new B() Begin---");
        A a2 = new B();
        System.out.println("---new B() end---\n");
        System.out.println("---new B() Begin---");
        B b = new B();
        System.out.println("---new B() end---\n");
        System.out.println("---new C() Begin---");
        C c = new C();
        System.out.println("---new C() end---\n");
        System.out.println("---new D() Begin---");
        D d = new D();
        System.out.println("---new D() end---\n");
        System.out.println("---new E() Begin---");
        E e = new E();
        System.out.println("---new E() end---\n");
    }
}

打印结果如下:

—new A() Begin—
init B static variable B1
init B static block 
init C static variable C1
init C static block 
init A variable  A2
init A block 
init A constructor 
init B variable  B2
init B block 
init B constructor 
init C variable  C2
init C block 
init C constructor 
init A static variable A1
init A static block 
init A variable  A2
init A block 
init A constructor 
—new A() end—

—new B() Begin—
init A variable  A2
init A block 
init A constructor 
init B variable  B2
init B block 
init B constructor 
—new B() end—

—new B() Begin—
init A variable  A2
init A block 
init A constructor 
init B variable  B2
init B block 
init B constructor 
—new B() end—

—new C() Begin—
init A variable  A2
init A block 
init A constructor 
init B variable  B2
init B block 
init B constructor 
init C variable  C2
init C block 
init C constructor 
—new C() end—

—new D() Begin—
init D static variable D1
init D static block 
init A variable  A2
init A block 
init A constructor 
init B variable  B2
init B block 
init B constructor 
init D variable  D2
init D block 
init D constructor 
—new D() end—

—new E() Begin—
init E static variable E1
init E static block 
init A variable  A2
init A block 
init A constructor 
init E variable  E2
init E block 
init E constructor 
—new E() end—

 父类A

package com.other;

public class A {
    public static String A1 = "A1";
    public static C CC = new C();//当静态加载中遇到需要加载非静态的情况: 先加载非静态再加载静态(因为非静态可以访问静态,而静态不能访问非静态)
    public String A2 = "A2";


    public A(){//构造函数,默认先调用父类的无参构造函数
        System.out.println("init A constructor ");
    }

    static {//静态代码块,静态代码块是主动运行的,而静态方法是被动运行
        System.out.println("init A static variable " + A1);
        System.out.println("init A static block ");
    }

    {//构造代码块,构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行
        System.out.println("init A variable  " + A2);
        System.out.println("init A block ");
    }

    public void show(){//普通方法,通过对象才能运行这个方法

        {   //普通代码块,普通代码块和构造代码块的区别是,
            // 构造代码块是在类中定义的,普通代码块是在方法体中定义的
            System.out.println("普通代码块");
        }

    }

    public static void show2(){//静态方法,通过类名或者对象名才能访问
        {
            
             System.out.println("普通代码块");
            
        }
    }

}

子类B 

package com.other;

public class B extends A {

    public static String B1 = "B1";
    public String B2 = "B2";

    public B(){
        System.out.println("init B constructor ");
    }

    static {
        System.out.println("init B static variable " + B1);
        System.out.println("init B static block ");
    }

    {
        System.out.println("init B variable  " + B2);
        System.out.println("init B block ");
    }

}

 子子类C

package com.other;

public class C extends B {
    public static String C1 = "C1";
    public String C2 = "C2";

    public C(){
        System.out.println("init C constructor ");
    }

    static {
        System.out.println("init C static variable " + C1);
        System.out.println("init C static block ");
    }

    {
        System.out.println("init C variable  " + C2);
        System.out.println("init C block ");
    }
}

 子子类D

package com.other;

public class D extends B {
    public static String D1 = "D1";
    public String D2 = "D2";

    public D(){
        System.out.println("init D constructor ");
    }

    static {
        System.out.println("init D static variable " + D1);
        System.out.println("init D static block ");
    }

    {
        System.out.println("init D variable  " + D2);
        System.out.println("init D block ");
    }
}

 子类E

package com.other;

public class E extends A {
    public static String E1 = "E1";
    public String E2 = "E2";

    public E(){
        System.out.println("init E constructor ");
    }

    static {
        System.out.println("init E static variable " + E1);
        System.out.println("init E static block ");
    }

    {
        System.out.println("init E variable  " + E2);
        System.out.println("init E block ");
    }

}


版权声明:本文为liqita原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。