Java子類和父類的初始化執行順序
要明白子類和父類的初始化執行順序,只需要知曉以下三點,就不會再弄錯了。
1.建立子類物件時,子類和父類的靜態塊和構造方法的執行順序為:父類靜態塊->子類靜態塊->父類構造器->子類構造器。深入理解為什麼是這個順序,可以看我這篇文章:從京東面試題看java類和物件的初始化
2.靜態變數的宣告和賦值,宣告會在靜態塊之前,賦值運算將會合併到靜態塊中,順序和原始碼中的順序一致。舉例如下:
原始碼
public class P {
public static int a = 1;
static {
int b = 2;
}
public static int c = 3;
}
在編譯器編譯後,會變成這樣子
public class P {
public static int a;
public static int c;
static {
a = 1;
int b = 2;
c = 3;
}
}
我們來看,編譯後的位元組碼是怎樣的,使用命令可以反編譯類的位元組碼:javap -v -p P.class
{
public static int a;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC
public static int c;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=1, args_size=0
0: iconst_1
1: putstatic #2 // Field a:I
4: iconst_2
5: istore_0
6: iconst_3
7: putstatic #3 // Field c:I
10: return
}
我去掉了編譯器生成的構造方法以及一些無關資訊,我們可以看到位元組碼中,a、c的宣告在前面(其實這個不是重點),在static{}塊中,pc 0~1兩個指令,為靜態欄位a賦值1,pc 4~5兩個指令,為第一個區域性變數,也就是變數b賦值2,pc 6~7兩個指令,為靜態欄位c賦值3。可以看到合併後的static塊,a的賦值在原靜態塊程式碼之前,c的賦值在原靜態塊程式碼之後,這個順序和原始碼中ac的宣告順序一致。
3.成員變數的宣告和賦值,與靜態變數相同的是成員變數的賦值也會合併到構造器中,不同的是合併後的順序,成員變數的賦值是在構造器的前面。舉例如下:
原始碼 鄭州專業婦科醫院
public class P {
public int a = 1;
public P() {
int b = 2;
}
public int c = 3;
}
編譯後的程式碼,會像這個樣子
public class P {
public int a;
public int c;
public P() {
a = 1;
c = 3;
int b = 2;
}
}
再來看看編譯後的位元組碼是怎樣的
public int a;
descriptor: I
flags: ACC_PUBLIC
public int c;
descriptor: I
flags: ACC_PUBLIC
public P();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field a:I
9: aload_0
10: iconst_3
11: putfield #3 // Field c:I
14: iconst_2
15: istore_1
16: return
欄位a和c的宣告在前面,然後看構造器P()的位元組碼,pc 0~1兩個指令,是先呼叫P的父類Object的構造器,位元組碼中的構造器方法使用來表示的。pc 4~6三個指令,為成員變數a賦值1。pc9~11三個指令,為成員變數c賦值3,pc 14~15兩個指令,為下表為1的區域性變數賦值為2,也就是區域性變數b=2。所以可以看出,成員變數賦值邏輯合併到構造器後,是在呼叫父類構造器之後,原有構造器程式碼之前。
回過頭來,你明白了子類父類初始化各個方法的執行順序,而欄位的初始化賦值也是合併到方法裡,所以建立子類物件時,子類父類各個部分的執行順序都已瞭然。
總結:
1.講解了子類父類初始化時方法執行順序,包括的靜態塊和構造器方法,靜態塊也是方法,靜態塊在jvm中的方法名叫。
2.講解了欄位的賦值是如何合併到方法中,靜態欄位賦值合併到靜態塊中,成員變數賦值合併到構造器方法中。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2670040/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java類的基本執行順序Java
- java類初始化的順序Java
- Java 類初始化順序Java
- Java類初始化順序Java
- 子類繼承父類(父類和子類裡:塊、靜態塊、構造和方法覆寫)之間呼叫順序繼承
- Java中,類與類,類中的程式碼執行順序Java
- Java類(繼承)初始化順序Java繼承
- 總結類初始化時的程式碼執行順序
- java類內部程式碼執行順序Java
- day-25-類的繼承順序-父類對子類的約束-多型-佇列和棧繼承多型佇列
- C#類中方法的執行順序C#
- 淺談Java類中的變數初始化順序Java變數
- java類載入順序Java
- Java類初始化執行流程Java
- JVM類載入機制與類初始化順序JVM
- 一張截圖概括父、子、孫元件事件鉤子的執行順序元件事件
- c#類的成員初始化順序C#
- java中父類宣告子類例項化Java
- load 和 initialize 方法的執行順序以及類和物件的關係物件
- 類的成員變數的初始化順序變數
- Java父子類載入順序Java
- 類的繼承_子類繼承父類繼承
- Java的類的例項化順序Java
- 父類和子類的建構函式問題函式
- 父類和子類之間的轉換問題
- java中多型的理解——父類引用指向子類物件Java多型物件
- 建立派生類物件,建構函式的執行順序物件函式
- 類script標籤,非同步載入,順序執行非同步
- Java 中建立子類物件會建立父類物件麼?Java物件
- 如何理解Python3中的子類和父類?Python
- 類的例項化順序和分析
- Java初始化順序Java
- C# 繼承 子類(派生類) 父類(基類)C#繼承
- 關於CSS中的定位使用子絕父相(子類絕對位置和父類相對位置)CSS
- JAVA物件的初始化順序Java物件
- 鏈式-父類中返回子類物件物件
- 子父類中函式函式
- java執行緒優先順序Java執行緒