經常說靜態代碼塊先執行…原理如下
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
大佬的文章真的非常棒,強烈推薦。