Java中不同情況下的執行順序整理:
阿新 • • 發佈:2018-12-17
初始化順序:父靜態變數、父靜態程式碼塊、子類靜態變數、子類靜態程式碼塊、父類非靜態變數、父類非靜態程式碼塊、父類構造器、子類非靜態變數、子類非靜態程式碼塊、子類建構函式。
執行順序:父類B靜態程式碼塊->子類A靜態程式碼塊->父類B非靜態程式碼塊->父類B建構函式->子類A非靜態程式碼塊->子類A建構函式
例如:
class A { public A() { System.out.println("A的構造方法"); } public static int j = print(); public static int print() { System.out.println("A print"); return 521; } } public class Test1 extends A { public Test1() { System.out.println("Test1的構造方法"); } public static int k = print(); public static int print() { System.out.println("Test print"); return 522; } public static void main(String[] args) { System.out.println("main start"); Test1 t1 = new Test1(); } }
輸出結果為:
A print
Test print
main start
A的構造方法
Test1的構造方法
2. 類載入過程中,可能呼叫了例項化過程(因為static可以修飾方法,屬性,程式碼塊,內部類),此時則會暫停類載入過程而先執行例項化過程(被打斷),執行結束再進行類載入過程,如下所示:【較難】
public class Text { public static int k = 0; public static Text t1 = new Text("t1"); public static Text t2 = new Text("t2"); public static int i = print("i"); public static int n = 99; public int j = print("j"); { print("構造塊"); } static { print("靜態塊"); } public Text(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++i; ++n; } public static int print(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; return ++i; } public static void main(String args[]) { Text t = new Text("init"); } }
執行結果 :
1:j i=0 n=0
2:構造塊 i=1 n=1
3:t1 i=2 n=2
4:j i=3 n=3
5:構造塊 i=4 n=4
6:t2 i=5 n=5
7:i i=6 n=6
8:靜態塊 i=7 n=99
9:j i=8 n=100
10:構造塊 i=9 n=101
11:init i=10 n=102
過程解讀:首先會對靜態變數進行初始化,對t1進行初始化時呼叫非靜態方法,所以會被打斷,先執行非靜態變數的初始化,print(j),然後執行非靜態程式碼塊,最後才會執行對t1的初始化,同樣,對於t2的初始化採取一樣的操作,故而前六行的輸出結果如上所示,然後對i進行初始化,呼叫靜態方法,然後執行靜態程式碼塊的初始化,最後對非靜態變數、非靜態程式碼塊進行初始化,最後執行main方法中的程式碼。
public class Son{
Father father = new Father();
static{
System.out.println("Son static");
}
public Son(){
System.out.println("Son()");
}
}
public class Father {
static{
System.out.println("Father static");
}
public Father(){
System.out.println("Father()");
}
}
public class Main{
public static void main(String[] args){
Son son = new Son();
}
}
結果為:
Son static
Father static
Father()
Son()
過程解讀:先執行static程式碼塊,再初始化成員變數,再執行構造方法。
4.涉及子類與父類時的執行順序:
public class Son extends Father{
//Father father = new Father();
static{
System.out.println("Son static");
}
public Son(){
System.out.println("Son()");
}
}
public class Father {
static{
System.out.println("Father static");
}
public Father(){
System.out.println("Father()");
}
}
public class Main{
public static void main(String[] args){
Son son = new Son();
}
}
執行結果如下:
Father static
Son static
Father()
Son()
過程解讀:先執行父類的static程式碼塊,再執行子類static,再執行構造方法。
5.多次建立物件,執行順序:
public class Test_Static_Class {
//靜態程式碼塊
static {
System.out.println("靜態程式碼塊");
}
{
System.out.println("構造塊1");
}
//構造方法
public Test_Static_Class() {
System.out.println("執行了構造方法");
}
//普通的成員方法
public void test() {
System.out.println("在方法中的普通程式碼塊");
//普通的程式碼塊
{
System.out.println("普通程式碼塊");
}
}
public static void main(String[] args) {
System.out.println("執行了主方法");
System.out.println("--------------------");
new Test_Static_Class();
System.out.println("------第二次建立物件---------------");
new Test_Static_Class();
System.out.println("------第三次建立物件---------------");
new Test_Static_Class().test();
}
//構造塊
{
System.out.println("構造塊2");
}
}
執行結果:
過程解讀:多次建立物件,靜態程式碼塊只執行一次,且最先執行。接下來執行的是構造快,構造塊會每建立一個物件執行一次,且多個構造塊會由上到下的執行。