java类的加载顺序,静态块 非静态块 构造器、属性、方法等

先看最终结论:

1、父类静态变量和静态代码块(先声明的先执行);

2、子类静态变量和静态代码块(先声明的先执行);

3、父类的变量和代码块(先声明的先执行);

4、父类的构造函数;

5、子类的变量和代码块(先声明的先执行);

6、子类的构造函数。

 

第1次测试

三个类如下


public class Parent {
    static String parentStaticValue = "parentStaticValue";
    String parentValue = "parentValue";

    Parent() {
        System.out.println("parent constructor");
    }

    static {
        System.out.println("parent static block");
    }

    {
        System.out.println("parent block");
    }

    static void parentStaticMethod() {
        System.out.println("parentStaticMethod");
    }

    void parentMethod() {
        System.out.println("parentMethod");
    }
}



public class Child extends Parent {
    static String childStaticValue = "childStaticValue";
    String childValue = "childValue";

    public Child() {
        System.out.println("child constructor");
    }

    static {
        System.out.println("child static block");
    }

    {
        System.out.println("child block");
    }

    static void childStaticMethod() {
        System.out.println("childStaticMethod");
    }

    void childMethod() {
        System.out.println("childMethod");
    }

}




public class ChildTest {

    public static void main(String[] args) {
        System.out.println("第1次 new Child()");
        new Child();
        System.out.println("第2次 new Child()");
        new Child();
    }

}

运行Test类输入结果

 结论1

父类的静态代码块 —> 子类静态静态代码块 —> 父类非静态代码块 —> 父类构造器 —> 子类非静态代码块 —> 子类构造器

但是上面的测试不能类的属性和类的代码块加载顺序 

第2次测试

package top.lishuoboy.java_basic.class_load_order;

public class Parent2 {

    static String parentStaticValue1 = "parentStaticValue1";

    static {
        System.out.println("parent static block1");
    }

    static String parentStaticValue2 = "parentStaticValue2";

    Parent2() {
        System.out.println("parent constructor");
    }

}

public class Parent2Test {

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

 打断点执行Parent2Test,看输出结果

 

再看一下图,编译不通过,提示非法的引用

继续修改代码

public class Parent3 {

    static {
        System.out.println("parent static block1");
        run();
    }

    static String parentStaticValue = "parentStaticValue";


    static {
        System.out.println("parent static block2");
        run();
    }

    static void run() {
        System.out.println(parentStaticValue);
    }

    Parent3() {
        System.out.println("parent constructor");
    }

}



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

 输出结果(与run方法的书写顺序无关)

 

结论2

静态块和静态属性代码按代码书写顺序加载。非静态也一样,不再代码演示。结论如下:

(静态)变量和(静态)代码块的也是有执行顺序的,与代码书写的顺序一致。在(静态)代码块中可以使用(静态)变量,但是被使用的(静态)变量必须在(静态)代码块前面声明

 

最终结论:

1、父类静态变量和静态代码块(先声明的先执行);

2、子类静态变量和静态代码块(先声明的先执行);

3、父类的变量和代码块(先声明的先执行);

4、父类的构造函数;

5、子类的变量和代码块(先声明的先执行);

6、子类的构造函数。

那么类的方法什么时候加载呢?

 

补充

1、修改Test,调用子类的父类的静态属性

public class Test {


    public static void main(String[] args) {
        System.out.println("第1次 Child.parentStaticValue");
        String a = Child.parentStaticValue;
        System.out.println("第2次 Child.parentStaticValue");
        String b = Child.parentStaticValue;
    }

}

输出结果 

 

2 、修改Test,调用子类的静态属性

public class Test {


    public static void main(String[] args) {
        System.out.println("第1次 Child.childStaticValue");
        String a = Child.childStaticValue;
        System.out.println("第2次 Child.childStaticValue");
        String b = Child.childStaticValue;
    }

}

 输出结果 

 

结论,自己看吧

 

 

 

posted on 2019-09-10 17:34  小石头小祖宗  阅读(6)  评论(0编辑  收藏  举报  来源

导航