java 類的實例化過程,其中的相關順序 包括有繼承的子類等復雜情況,靜態成員變量的初始化順序,這其中jvm在干什么

Java類的實例化過程及初始化順序

Java類的實例化過程涉及多個步驟,特別是在存在繼承關系和靜態成員的情況下。下面我將詳細解釋整個過程,包括JVM在其中的角色。

1. 類加載階段(JVM的工作)

在實例化一個類之前,JVM首先需要加載這個類:

  1. 加載:JVM查找并加載類的二進制數據(.class文件)

  2. 驗證:確保加載的類正確無誤,符合JVM規范

  3. 準備:為類的靜態變量分配內存,并設置默認初始值(0, null, false等)

  4. 解析:將符號引用轉換為直接引用

  5. 初始化:執行類的靜態初始化代碼和靜態變量初始化

2. 實例化過程順序(包含繼承)

當使用new關鍵字創建對象時,完整的初始化順序如下:

父類靜態成員和靜態代碼塊

  1. 父類的靜態變量初始化

  2. 父類的靜態代碼塊(按代碼中的順序執行)

子類靜態成員和靜態代碼塊

  1. 子類的靜態變量初始化

  2. 子類的靜態代碼塊(按代碼中的順序執行)

父類實例成員和構造代碼塊

  1. 父類的實例變量初始化

  2. 父類的構造代碼塊(按代碼中的順序執行)

  3. 父類的構造函數(如果沒有顯式調用其他構造函數,則調用默認無參構造)

子類實例成員和構造代碼塊

  1. 子類的實例變量初始化

  2. 子類的構造代碼塊(按代碼中的順序執行)

  3. 子類的構造函數

3. JVM在實例化過程中的工作

在整個實例化過程中,JVM負責:

  1. 內存分配:為對象和它的實例變量分配堆內存

  2. 初始化默認值:將所有實例變量設置為默認值(0, null, false等)

  3. 方法表設置:為對象設置方法表(用于動態綁定和多態)

  4. 執行初始化代碼:按照上述順序執行各種初始化代碼

  5. 構造器鏈調用:確保父類構造器在子類構造器之前被調用

  6. 處理多態:在運行時確定實際要調用的方法版本

4. 示例代碼

class Parent {static {System.out.println("Parent static block");}{System.out.println("Parent instance block");}Parent() {System.out.println("Parent constructor");}
}class Child extends Parent {static {System.out.println("Child static block");}{System.out.println("Child instance block");}Child() {System.out.println("Child constructor");}
}public class Main {public static void main(String[] args) {new Child();}
}

輸出順序:

Parent static block
Child static block
Parent instance block
Parent constructor
Child instance block
Child constructor

5. 特殊情況

  • 如果類中有多個靜態變量和靜態代碼塊,它們按照在代碼中出現的順序執行

  • 實例變量和構造代碼塊也是按照代碼中的順序執行

  • 如果構造函數中顯式調用了其他構造函數(this()或super()),則先執行被調用的構造函數

  • 如果父類沒有無參構造器,子類必須顯式調用父類的某個構造器(super(...))

理解這些初始化順序對于避免NullPointerException和其他初始化相關的問題非常重要,特別是在復雜的繼承層次結構中。

關于 Java 類的實例化過程

??整體順序正確,但可以補充一些關鍵細節:

需要修正/補充的點:

  1. 靜態初始化(JVM 類加載階段)

    • 靜態變量和靜態代碼塊的初始化順序?僅發生在類首次被主動使用時(比如?new、訪問靜態成員、Class.forName()?等),而不是在程序啟動時全部加載。

    • 如果類已經被加載過(比如之前已經調用過靜態方法),則不會再次執行靜態初始化。

  2. 實例初始化

    • final?實例變量?的初始化必須在構造函數完成之前完成,否則編譯錯誤。

    • 如果類沒有顯式構造函數,JVM 會提供默認無參構造,但如果父類沒有無參構造,子類必須顯式調用?super(...),否則編譯失敗。

  3. JVM 的隱含操作

    • 在構造函數真正執行前,JVM 會?隱式初始化所有實例變量為默認值0/null/false),然后才執行顯式賦值或初始化塊。

    • 如果存在?實例變量直接賦值(如?int x = 5;),這些賦值會在構造代碼塊之前執行。

示例修正:

class Parent {static { System.out.println("Parent static block"); }{ System.out.println("Parent instance block"); }Parent() { System.out.println("Parent constructor"); }
}class Child extends Parent {static { System.out.println("Child static block"); }{ System.out.println("Child instance block"); }int x = initX(); // 這個會在實例塊之后執行嗎?? 實際在實例塊之前!Child() { System.out.println("Child constructor"); }private int initX() { System.out.println("Initializing x"); return 1; }
}public class Main {public static void main(String[] args) {new Child();}
}

實際輸出:

Parent static block
Child static block
Parent instance block
Parent constructor
Initializing x  // 變量初始化在實例塊之前!
Child instance block
Child constructor

1.?final?實例變量必須在構造函數完成前初始化(否則編譯錯誤)

final?實例變量必須在?對象構造完成前?被賦值,且只能賦值一次。有三種方式初始化:

  1. 聲明時直接賦值

  2. 在實例初始化塊中賦值

  3. 在每個構造函數中賦值

class FinalExample {final int x;          // ? 如果不初始化,編譯報錯final int y = 10;     // ? 方式1:聲明時賦值final int z;{ z = 20; }           // ? 方式2:實例初始化塊賦值FinalExample() {x = 30;           // ? 方式3:構造函數中賦值}FinalExample(int val) {x = val;         // ? 另一個構造函數也必須賦值}
}
錯誤示例:
class FinalError {final int x;  // ? 編譯錯誤:未初始化final變量xFinalError() {// 忘記給x賦值}
}

2. 父類沒有無參構造時,子類必須顯式調用?super(...)

如果父類?沒有無參構造,子類?必須?在構造函數的第一行顯式調用?super(...),否則編譯失敗。

示例代碼:
class Parent {Parent(int value) {  // ?父類只有帶參構造,沒有默認無參構造System.out.println("Parent constructor: " + value);}
}class Child extends Parent {Child() {super(10);  // ? 必須顯式調用父類構造,否則編譯錯誤System.out.println("Child constructor");}
}public class Main {public static void main(String[] args) {new Child();}
}
輸出:
Parent constructor: 10
Child constructor
錯誤示例:
class Child extends Parent {Child() {  // ? 編譯錯誤:父類Parent中沒有默認構造函數System.out.println("Child constructor");}
}

關鍵總結

  1. final?實例變量

    • 必須且只能賦值一次。

    • 必須在構造完成前初始化(三種方式選其一)。

  2. 構造函數繼承規則

    • 如果父類?沒有無參構造,子類?必須顯式調用?super(...)

    • 如果父類有無參構造,子類可以不寫?super()(JVM 會隱式調用)。

這些規則由?Java 語言規范(JLS)?強制約束,編譯器會嚴格檢查。

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/diannao/80958.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/diannao/80958.shtml
    英文地址,請注明出處:http://en.pswp.cn/diannao/80958.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Sce2DriveX: 用于場景-到-駕駛學習的通用 MLLM 框架——論文閱讀

    《Sce2DriveX: A Generalized MLLM Framework for Scene-to-Drive Learning》2025年2月發表,來自中科院軟件所和中科院大學的論文。 端到端自動駕駛直接將原始傳感器輸入映射到低級車輛控制,是Embodied AI的重要組成部分。盡管在將多模態大語言模型&…

    【題解-Acwing】870. 約數個數

    題目:870. 約數個數 題目描述 給定 n 個正整數 ai,請你輸出這些數的乘積的約數個數,答案對 109+7 取模。 輸入 第一行包含整數 n。 接下來 n 行,每行包含一個整數 ai。 輸出 輸出一個整數,表示所給正整數的乘積的約數個數,答案需對 109+7 取模。 數據范圍 1 ≤ …

    創龍全志T536全國產(4核A55 ARM+RISC-V+NPU 17路UART)工業開發板硬件說明書

    前 言 本文檔主要介紹TLT536-EVM評估板硬件接口資源以及設計注意事項等內容。 T536MX-CXX/T536MX-CEN2處理器的IO電平標準一般為1.8V、3.3V,上拉電源一般不超過3.3V或1.8V,當外接信號電平與IO電平不匹配時,中間需增加電平轉換芯片或信號隔離芯片。按鍵或接口需考慮ESD設計…

    Redis 持久化雙雄:RDB 與 AOF 深度解析

    Redis 是一種內存數據庫,為了保證數據在服務器重啟或故障時不丟失,提供了兩種持久化方式:RDB(Redis Database)和 AOF(Append Only File)。以下是它們的詳細介紹: 一、RDB 持久化 工…

    數據結構|并查集

    Hello !朋友們,這是我在學習過程中梳理的筆記,以作以后復習回顧,有時略有潦草,一些話是我用自己的話描述的,可能不夠準確,還是感謝大家的閱讀! 目錄 一、并查集Quickfind 二、兩種算…

    【GPU 微架構技術】Pending Request Table(PRT)技術詳解

    PRT(Pending Request Table)是 GPU 中用于管理 未完成內存請求(outstanding memory requests)的一種硬件結構,旨在高效處理大規模并行線程的內存訪問需求。與傳統的 MSHR(Miss Status Handling Registers&a…

    遠程訪問你的家庭NAS服務器:OpenMediaVault內網穿透配置教程

    文章目錄 前言1. OMV安裝Cpolar工具2. 配置OMV遠程訪問地址3. 遠程訪問OMV管理界面4. 固定遠程訪問地址 前言 在這個數據爆炸的時代,無論是管理家人的照片和視頻,還是企業老板處理財務報表和技術文檔,高效的數據管理和便捷的文件共享已經變得…

    微服務架構下的熔斷與降級:原理、實踐與主流框架深度解析

    微服務架構下的熔斷與降級:原理、實踐與主流框架深度解析 在現代分布式系統中,熔斷 (Circuit Breaker) 和 降級 (Degrade) 是保障系統彈性與高可用性的核心機制。本文將系統解析兩者的原理、區別與協同方式,并結合主流框架 (Resilience4j、S…

    docker-vllm運行大模型

    vllm鏡像下載,國內代理源 vllm/vllm-openai - Docker Image - 毫秒鏡像https://1ms.run/r/vllm/vllm-openai 執行下載docker pull docker.1ms.run/vllm/vllm-openai 查看本地鏡像 查看鏡像 查看鏡像 docker images導出鏡像 docker save -o E:\docker\ollama.tar …

    基于tabula對pdf中多個excel進行識別并轉換成word中的優化(四)

    對上一節進行優化: 1、識別多個excel 2、將表格中的nan替換成空字符串 一、示例中的pdf內容 二、完整代碼參考: import tabula import numpy as np from docx import Document from docx.oxml.ns import qn from docx.oxml import OxmlElementdef get_t…

    【10分鐘讀論文】Power Transmission Line Inspections電力視覺水文

    標題Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems 2024 評分一顆星 論文《Power Transmission Line Inspections: Methods, Challenges, Current Status and Usage of Unmanned Aerial Systems》的核心內…

    linux安裝ragflow

    先安裝docker,操作步驟參考文章: Linux安裝Docker docker安裝完畢,下載ragflow源碼: https://github.com/infiniflow/ragflow 下載完成,進入docker文件夾中,修改.env文件,因為默認安裝的是sli…

    學習記錄:DAY20

    技術探索之旅:YAML配置,依賴注入、控制反轉與Java注解 前言 最近有點懶了,太松懈可不行。為了讓自己保持學習的動力,我決定將最近的學習內容整理成博客,目標是讓未來的自己也能輕松理解。我會盡量以整體記錄的方式呈…

    MCP:人工智能時代的HTTP?探索AI通信新標準

    每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎?訂閱我們的簡報,深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同,從行業內部的深度分析和實用指南中受益。不要錯過這個機會,成為AI領…

    首版次誤區有哪些?與軟件測試報告又有什么聯系?

    在軟件開發與測試領域,"首版次"這一概念關乎軟件的版本控制與管理,是確保產品質量和發布節奏的重要環節。首版次,通常是指軟件產品第一個對外發布或內部驗收的版本號,標志著一次完整開發周期的結束和下一階段工作的開始…

    Laravel+API 接口

    LaravelAPI 接口 網課連接:BIlibili. 中文文檔. 1.RestFul Api編碼風格 一、API設計 修改hosts,C:\Windows\System32\drivers\etc\hosts,增加127.0.0.1 api.lv8.com # Laravel 框架 用這個域名來測試(推薦規范) 在…

    MIT6.S081-lab7前置

    MIT6.S081-lab7前置 這部分包含了設備中斷和鎖的內容 設備中斷 之前系統調用的時候提過 usertrap ,而我們的設備中斷,比如計時器中斷也會在這里執行,我們可以看看具體的邏輯: void usertrap(void) {int which_dev 0;if((r_sst…

    Linux 下編譯BusyBox

    一、linux下編譯 1.拉取busybox源碼 git clone https://github.com/mirror/busybox.git 內容如下 2.配置make,建議在linux下單獨開一個終端執行 進入busybox源碼目錄,使用如下命令 make menuconfig 3.報錯 解決辦法: 安裝ncurses sud…

    Element:Cheack多選勾選效果邏輯判斷

    效果展示 取消子級勾選&#xff0c;父級的勾選效果 代碼合集 &#xff08;1&#xff09;組件代碼 fromlist.cheackType 類型&#xff0c;permissio表示是權限. fromlist:[{id:1,children:[{...}]},...]傳遞的數據大致結構 <!-- 操作權限 --><template v-if"…

    【3DMax腳本MaxScript開發:創建高效模型虛擬體綁定和材質管理系統,從3DMax到Unreal和Unity引擎_系列第一篇】

    3ds Max 腳本開發 3ds Max 腳本開發&#xff1a;創建高效模型虛擬體綁定和材質管理系統3ds Max 插件制作背景&#xff1a;設計思路一、場景節點收集與過濾廢話不多說&#xff0c;直接上完整代碼&#xff1a;界面定義與基礎設置界面控件創建狀態變量核心邏輯函數過濾選項改變事件…