经常说静态代码块先执行.......原理如下
public static void main(String[] args) {
//为什么所谓的静态代码块先执行,是由于加载类<clinit>类构造方法,
//是类级别的,只执行一次,编译器自动收集类中所有的static变量和static代码块
//中语句合并而成,编译器收集的顺序是由于程序源码顺序决定
// StaticTest staticTest = new StaticTest();
}
如下代码:static StaticTest st = new StaticTest();位置不同,执行的顺序依据类加载的不同而不同
public class StaticTest {
public static void main(String[] args) {
staticFunction();
}
// 在类的初始化阶段需要做的是执行类构造器<clinit>(),需要指出的是,
// 类构造器本质上是编译器收集所有静态语句块和类变量的赋值语句按语句
// 在源码中的顺序合并生成类构造器<clinit>()。
// 因此,对上述程序而言,JVM将先执行第一条静态变量的赋值语句:
// static StaticTest st = new StaticTest();
{
System.out.println("我是构造代码块,我刚在前面");
// 实例代码块
System.out.println("2");
}
//顺序(放在 new 静态实例前后)
static {
System.out.println("我是静态代码块,我刚在后面");
//静态代码块
System.out.println("1");
}
StaticTest() { // 实例构造器
System.out.println("3");
System.out.println("a=" + a + ",b=" + b);
}
public static void staticFunction() { // 静态方法
System.out.println("4");
}
int a = 110; // 实例变量
static int b = 112; // 静态变量
// static StaticTest st = new StaticTest();
}
- 初始化阶段是执行类构造器< clinit >()方法的过程。< clinit >()方法是由编译器自动收集类中的所有类变量(也叫静态变量)的赋值动作和静态语句块static{}中的语句合并产生的。
- 编译器收集的顺序是由语句在源文件中出现的顺序所决定的
- init是对象构造器方法,也就是说在程序执行 new 一个对象调用该对象类的 constructor 方法时才会执行init方法,对非静态变量初始化;而clinit是类构造器方法,也就是在jvm进行类加载—–验证—-解析—–初始化,中的初始化阶段jvm会调用clinit方法。
参考:https://blog.csdn.net/justloveyou_/article/details/72466105
大佬的文章真的非常棒,强烈推荐。