經(jīng)常說靜態(tài)代碼塊先執(zhí)行.......原理如下
public static void main(String[] args) {
//為什么所謂的靜態(tài)代碼塊先執(zhí)行劣像,是由于加載類<clinit>類構(gòu)造方法乡话,
//是類級別的,只執(zhí)行一次耳奕,編譯器自動收集類中所有的static變量和static代碼塊
//中語句合并而成绑青,編譯器收集的順序是由于程序源碼順序決定
// StaticTest staticTest = new StaticTest();
}
如下代碼:static StaticTest st = new StaticTest();位置不同诬像,執(zhí)行的順序依據(jù)類加載的不同而不同
public class StaticTest {
public static void main(String[] args) {
staticFunction();
}
// 在類的初始化階段需要做的是執(zhí)行類構(gòu)造器<clinit>(),需要指出的是闸婴,
// 類構(gòu)造器本質(zhì)上是編譯器收集所有靜態(tài)語句塊和類變量的賦值語句按語句
// 在源碼中的順序合并生成類構(gòu)造器<clinit>()坏挠。
// 因此,對上述程序而言邪乍,JVM將先執(zhí)行第一條靜態(tài)變量的賦值語句:
// static StaticTest st = new StaticTest();
{
System.out.println("我是構(gòu)造代碼塊降狠,我剛在前面");
// 實(shí)例代碼塊
System.out.println("2");
}
//順序(放在 new 靜態(tài)實(shí)例前后)
static {
System.out.println("我是靜態(tài)代碼塊,我剛在后面");
//靜態(tài)代碼塊
System.out.println("1");
}
StaticTest() { // 實(shí)例構(gòu)造器
System.out.println("3");
System.out.println("a=" + a + ",b=" + b);
}
public static void staticFunction() { // 靜態(tài)方法
System.out.println("4");
}
int a = 110; // 實(shí)例變量
static int b = 112; // 靜態(tài)變量
// static StaticTest st = new StaticTest();
}
- 初始化階段是執(zhí)行類構(gòu)造器< clinit >()方法的過程庇楞。< clinit >()方法是由編譯器自動收集類中的所有類變量(也叫靜態(tài)變量)的賦值動作和靜態(tài)語句塊static{}中的語句合并產(chǎn)生的榜配。
- 編譯器收集的順序是由語句在源文件中出現(xiàn)的順序所決定的
- init是對象構(gòu)造器方法,也就是說在程序執(zhí)行 new 一個對象調(diào)用該對象類的 constructor 方法時才會執(zhí)行init方法吕晌,對非靜態(tài)變量初始化蛋褥;而clinit是類構(gòu)造器方法,也就是在jvm進(jìn)行類加載—–驗(yàn)證—-解析—–初始化睛驳,中的初始化階段jvm會調(diào)用clinit方法烙心。
參考:https://blog.csdn.net/justloveyou_/article/details/72466105
大佬的文章真的非常棒,強(qiáng)烈推薦乏沸。