静态代码块、静态变量、成员变量等加载顺序详解

  • Post author:
  • Post category:其他



目录


1 单个类的初始化顺序


2. 父子类初始化顺序


1 .单个类的初始化顺序

一个类 无论创建多少对象,静态数据只占用一份存储区域,且只在类第一次初始化的时候进行静态数据初始化

顺序如下:

单个类而言: 静态变量/静态代码块 –> 成员变量(普通代码块) –> 构造方法 –> 静态方法


构造方法本身也是静态方法

栗子

public class TestStatic {
    {
        System.out.println("代码块1");
    }
    /*静态代码块*/
    static {
        System.out.println("静态代码块");
    }
    static Test test = new Test();

    String s = "成员变量";

    TestStatic (){
        System.out.println(s + "TestStatic 构造方法");
    }
    {
        System.out.println("代码块2");
    }

    public static void main(String[] args) {
        new TestStatic();
    }
}

class Test {
    Test(){
        System.out.println("test构造方法");
    }
}
/*结果如下
静态代码块
test构造方法
代码块1
代码块2
成员变量TestStatic 构造方法

Process finished with exit code 0
说明 在加载main 方法之前 需要先加载这个类 
所以在不实例化这个对象之前的结果是
静态代码块
test构造方法

Process finished with exit code 0
加载顺序: 加载类 --> 静态变量、静态代码块(先后顺序加载) --> 成员变量、一般代码块 --> 构造方法


加载顺序: 加载类 –> 静态变量、静态代码块(先后顺序加载) –> 成员变量、普通代码块 –> 构造方法

再来个栗子

class Bowl {
    Bowl(int marker) {
        System.out.println("Bowl(" + marker + ")");
    }

    void f1(int marker) {
        System.out.println("f1(" + marker + ")");
    }
}

class Table {
    static Bowl bowl1 = new Bowl(1);
    Table() {
        System.out.println("Table()");
        bowl2.f1(1);
    }
    void f2(int marker){
        System.out.println("f2(" + marker + ")");
    }
    static Bowl bowl2 = new Bowl(2);
}

class Cupboard {
    Bowl bowl3 = new Bowl(3);
    static Bowl bowl4 = new Bowl(4);
    Cupboard (){
        System.out.println("Cupboard()");
        bowl4.f1(2);
    }
    void f3(int marker){
        System.out.println("f3(" + marker +  ")");
    }
    static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {

    public static void main(String[] args) {
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        table.f2(1);
        cupboard.f3(2);
    }
    static Table table = new Table();
    static Cupboard cupboard = new Cupboard();
}

/**
结果如下: 
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(2)

Process finished with exit code 0
**/

2. 父子类初始化顺序

多个类 其实也差不多,顺序如下:

父类静态变量、静态代码块 –> 子类静态变量、静态代码块 –> 父类成员变量、普通代码块–> 父类构造方法 –> 子类成员变量、普通代码块–> 子类构造方法

栗子来了

/*子类*/
public class Child extends Parent {

    static {
        System.out.println("子类静态代码块");
    }
    static TestChild test = new TestChild();

    {
        System.out.println("子类代码块1");
    }

    String s = "子类成员变量";

    {
        System.out.println("子类代码块2");
    }

    Child() {
        System.out.println("子类构造器" + s);
    }

    public static void main(String[] args) {
        Parent c = new Child();
    }

}
    class TestChild {
        TestChild (){
        System.out.println("用于测试子类静态变量顺序");
    }
}


/*父类*/
package com.windy.testBook.five;

/**
 * @Author windy
 * @Desp
 * @Date 2019-03-23 17:13
 */
public class Parent {

    static TestParent test = new TestParent();

    static {
        System.out.println("父类静态代码块");
    }
    Parent () {
        System.out.println("父类构造器" + s);
    }

    {
        System.out.println("父类代码块1");
    }

    String s = "父类成员变量";

    {
        System.out.println("父类代码块2");
    }
}
    class TestParent {
    TestParent (){
        System.out.println("用于测试父类静态变量顺序");
    }
}

/*结果
用于测试父类静态变量顺序
父类静态代码块
子类静态代码块
用于测试子类静态变量顺序
父类代码块1
父类代码块2
父类构造器父类成员变量
子类代码块1
子类代码块2
子类构造器子类成员变量

Process finished with exit code 0
*/


静态代码块或者静态变量是对象加载的时候进行的 只加载一次。如上面所有 只有一个存储区域。而成员变量或者普通代码块 每次实例的时候 都会执行一次 而且都优先于构造方法



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