Java——對(duì)象初始化順序使用詳解
一、 代碼塊的概念
在探究對(duì)象初始化順序之前,我們先通過代碼來了解一下代碼塊的概念。
class Test{
public static String str1; //靜態(tài)字段
public String str2; //普通字段
static{
//靜態(tài)代碼塊
}
{
//構(gòu)造代碼塊
}
public Test() {
//構(gòu)造函數(shù)
}
}
二、 創(chuàng)建子類對(duì)象時(shí),對(duì)象的初始化順序
1. 字段初始化、代碼塊和構(gòu)造函數(shù)的執(zhí)行順序
我們先看代碼和結(jié)果
public class CodeBlockTest {
public static void main(String[] args) {
Child child = new Child();
}
}
class Father {
public static String fatherStr1 = "fatherStr1(靜態(tài)字段初始化值)";
public String fatherStr2 = "fatherStr2(字段初始化值)";
static {
System.out.println("父類靜態(tài)代碼塊:" + fatherStr1);
fatherStr1 = "fatherStr1(靜態(tài)代碼塊賦值)";
}
{
System.out.println("父類構(gòu)造代碼塊:" + fatherStr2);
fatherStr2 = "fatherStr2(構(gòu)造代碼塊賦值)";
}
public Father() {
System.out.println("父類構(gòu)造函數(shù)塊:" + fatherStr2);
fatherStr2 = "fatherStr2(構(gòu)造函數(shù)賦值)";
}
}
class Child extends Father {
public static String childStr1 = "childStr1(靜態(tài)字段初始化值)";
public String childStr2 = "childStr2(字段初始化值)";
static {
System.out.println("子類靜態(tài)代碼塊:" + childStr1);
childStr1 = "childStr1(靜態(tài)代碼塊賦值)";
}
{
System.out.println("子類構(gòu)造代碼塊:" + childStr2);
childStr2 = "childStr2(構(gòu)造代碼塊賦值)";
}
public Child() {
System.out.println("子類構(gòu)造函數(shù):" + childStr2);
childStr2 = "childStr2(構(gòu)造函數(shù)賦值)";
}
}
// 輸出結(jié)果:
// 父類靜態(tài)代碼塊:fatherStr1(靜態(tài)字段初始化值)
// 子類靜態(tài)代碼塊:childStr1(靜態(tài)字段初始化值)
// 父類構(gòu)造代碼塊:fatherStr2(字段初始化值)
// 父類構(gòu)造函數(shù)塊:fatherStr2(構(gòu)造代碼塊賦值)
// 子類構(gòu)造代碼塊:childStr2(字段初始化值)
// 子類構(gòu)造函數(shù):childStr2(構(gòu)造代碼塊賦值)
通過每執(zhí)行一個(gè)代碼塊或構(gòu)造函數(shù),輸出字段在上一代碼塊執(zhí)行后的值,以此來探究對(duì)象的初始化順序。
由目前的輸出結(jié)果可知,對(duì)于對(duì)象的初始化順序,我們可以得出以下結(jié)論:
1. 父類靜態(tài)字段初始化
2. 父類靜態(tài)代碼塊、子類靜態(tài)字段初始化 (接下來探究?jī)烧叩捻樞颍?/p>
3. 子類靜態(tài)代碼塊
4. 父類普通字段初始化
5. 父類構(gòu)造代碼塊
6. 父類構(gòu)造函數(shù)
7. 子類普通字段初始化
8. 子類構(gòu)造代碼塊
9. 子類構(gòu)造函數(shù)
2. 父類靜態(tài)代碼塊和子類靜態(tài)字段初始化的執(zhí)行順序
還是一樣,我們通過代碼的執(zhí)行結(jié)果來探究?jī)烧唛g的執(zhí)行順序。
public class CodeBloacTest2 {
public static void main(String[] args) {
Child child = new Child();
}
}
class Father {
public static String fatherStr = "(靜態(tài)字段初始化值)";
static {
System.out.println("父類靜態(tài)代碼塊:fatherStr" + fatherStr);
fatherStr = "(靜態(tài)代碼塊賦值)";
}
}
class Child extends Father {
public static String childStr = fatherStr;
static {
System.out.println("子類靜態(tài)代碼塊:childStr = fatherStr" + childStr);
childStr = "(靜態(tài)代碼塊賦值)";
}
}
// 輸出結(jié)果:
// 父類靜態(tài)代碼塊:fatherStr(靜態(tài)字段初始化值)
// 子類靜態(tài)代碼塊:childStr = fatherStr(靜態(tài)代碼塊賦值)
我們?cè)谧宇愳o態(tài)字段childStr初始化的時(shí)候,賦的是父類靜態(tài)字段fatherStr的值。由輸出結(jié)果可知,childStr初始化后的值是父類靜態(tài)代碼塊執(zhí)行后賦予fatherStr的值。由此可知兩者的執(zhí)行順序?yàn)椋焊割愳o態(tài)代碼塊==>子類靜態(tài)字段初始化
三、 結(jié)論
父類靜態(tài)字段初始化
父類靜態(tài)代碼塊
子類靜態(tài)字段初始化
子類靜態(tài)代碼塊
父類普通字段初始化
父類構(gòu)造代碼塊
父類構(gòu)造函數(shù)
子類普通字段初始化
子類構(gòu)造代碼塊
子類構(gòu)造函數(shù)
通過結(jié)論我們可以很明顯的看出:static字段、代碼塊的執(zhí)行順序優(yōu)先于非static字段、代碼塊。這是因?yàn)樵陟o態(tài)域是屬于類的,在類加載后就一直存在;而普通域需要?jiǎng)?chuàng)建對(duì)象才能訪問。而在創(chuàng)建對(duì)象時(shí),需要先加載父類,然后再加載子類,因此父類的靜態(tài)字段初始化和靜態(tài)代碼塊執(zhí)行先于子類。
以上內(nèi)容希望對(duì)各位朋友有所幫助
相關(guān)文章
springboot的http.server.requests服務(wù)請(qǐng)求流程源碼
這篇文章主要為大家介紹了springboot的http.server.requests服務(wù)請(qǐng)求流程源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
SpringBoot整合liquibase的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot整合liquibase的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
JVM(Java?Virtual?Machine,Java虛擬機(jī))的作用詳解
JVM是Java語(yǔ)言實(shí)現(xiàn)“一次編寫,到處運(yùn)行”特性的基石,也是Java平臺(tái)的核心組成部分,其主要作用包括平臺(tái)無關(guān)性、內(nèi)存管理、運(yùn)行Java程序、安全性以及性能優(yōu)化,通過這些功能,JVM確保了Java程序的可移植性、高效性和安全性2025-03-03
使用Shiro實(shí)現(xiàn)登錄成功后跳轉(zhuǎn)到之前的頁(yè)面
這篇文章主要介紹了如何使用Shiro實(shí)現(xiàn)不同用戶登錄成功后跳轉(zhuǎn)到不同主頁(yè),實(shí)現(xiàn)此功能目前比較好的方法是用ajax的方法登錄,第二種方法是把用戶未登錄前的url存在session中,需要的朋友可以參考下2015-07-07
java實(shí)現(xiàn)同步回調(diào)的示例代碼
同步回調(diào)是一種在調(diào)用代碼中同步執(zhí)行回調(diào)函數(shù)的編程模式,在Java中,通過定義和實(shí)現(xiàn)接口來構(gòu)建同步回調(diào),本文就來介紹一下如何實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-09-09
Java Swing中的表格(JTable)和樹(JTree)組件使用實(shí)例
這篇文章主要介紹了Java Swing中的表格(JTable)和樹(JTree)組件使用實(shí)例,本文同時(shí)講解了表格和樹的基本概念、常用方法、代碼實(shí)例,需要的朋友可以參考下2014-10-10
MyBatis 接收數(shù)據(jù)庫(kù)中沒有的字段的解決
這篇文章主要介紹了MyBatis 接收數(shù)據(jù)庫(kù)中沒有的字段的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
java并發(fā)數(shù)據(jù)包Exchanger線程間的數(shù)據(jù)交換器
這篇文章主要為大家介紹了java并發(fā)數(shù)據(jù)包使用數(shù)據(jù)交換器Exchanger來進(jìn)行線程之間的數(shù)據(jù)交換。有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-03-03

