Java类初始化之clinit

初始化阶段就是执行类构造器<clinit>()方法的过程。<clinit>()并不是程序员在Java代码中直接编写的方法,而是Javac编译器的自动生成物。

<clinit>()方法是由编译器自动收集类中的所有类变量赋值动作和静态语句块(static{})中的语句合并产生的,收集顺序是按在源文件中的出现顺序决定的。静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块中可以赋值,但不能访问。

public class Test{
    static{
        i = 0;    //给变量赋值可以编译通过
        System.out.println(i);      //非法向前引用
    }

    static int i = 1;
}

<clinit>()方法与类的构造函数(在虚拟机视角中的实例构造器<init>()方法)不同,它不需要显式地调用父类构造器,Java虚拟机会保证子类的<clinit>()方法执行器前,父类的<clinit>()方法已经执行完毕。因此,在Java虚拟机中第一个被执行的<clinit>()方法的类型肯定就是java.lang.Object。

由于父类的<clinit>()方法先执行,也就意味着父类中定义的静态语句块优先于子类的变量赋值操作。

static class Parent{
    public static int A = 1;
    static{
        A = 2;
    }
}

static class Sub extends Parent{
    public static int B = A;
}

public static void main(String[] args){
    System.out.println(Sub.B);
}
posted @ 2020-12-27 02:10  maurrinho  阅读(670)  评论(0编辑  收藏  举报