侧边栏壁纸
  • 累计撰写 28 篇文章
  • 累计创建 34 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java虚拟机加载执行顺序详解:游乐园趣味图解 🎢

16uni
2025-06-18 / 0 评论 / 0 点赞 / 20 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

核心概念:把Java类加载想象成游乐园的运营过程:

  • 类加载阶段 = 开园准备(一次性)

  • 对象创建阶段 = 游客入园(每次new触发)

  • 方法调用阶段 = 游玩过程(自由调用)


🗺️ 整体加载流程图

虚拟机执行顺序1.svg


🌟 一、类加载阶段(游乐园开园准备)

当JVM首次使用类时(比如第一次new AmusementPark()或访问静态成员),触发一次性加载:

虚拟机执行顺序2.png

代码示例

public class AmusementPark {
    // 1. 静态常量 - 入园须知牌 🪧 (编译期确定)
    public static final String OPEN_TIME = "09:00";
    
    // 2. 静态变量 - 游客计数器 👥 (默认0 → 显式赋值)
    public static int totalVisitors = 0;
    
    // 3. 静态块 - 开园仪式 🎪 (按代码顺序执行)
    static {
        System.out.println("🎪 静态块:游乐园开园!");
        System.out.println("⏰ 开放时间:" + OPEN_TIME);
    }
}

执行顺序

  1. 静态常量 OPEN_TIME(像入园规则牌,立好就不变)

  2. 静态变量 totalVisitors(像游客计数器,开园时归零)

  3. 静态块(像开园仪式,只举行一次)

💡 场景:静态块适合初始化全局配置(如数据库连接池)


👨‍👩‍👧 二、对象创建阶段(游客入园)

每次new就像新游客入园,触发完整初始化流程:

虚拟机执行顺序3.svg

代码示例

public class AmusementPark {
    // 4. 实例变量 - 游客手环 💫 (每个游客独有)
    private String visitorBand;
    
    // 5. 实例块 - 安检通道 🛂 (在构造器之前执行)
    {
        System.out.println("🛂 实例块:游客通过安检");
        visitorBand = "VIP-" + System.currentTimeMillis(); // 生成唯一手环
    }
    
    // 6. 构造器 - 入园欢迎 🎉 (最终初始化)
    public AmusementPark(String name) {
        System.out.println("🎉 构造器:欢迎" + name + "!");
        totalVisitors++; // 更新静态计数器
    }
}

关键点

  • 实例块会在每个构造器中隐式插入(类似安检通道必经之路)

  • 构造器可重载,但实例块代码会统一执行

💡 场景:实例块适合对象公共初始化(如日志ID生成)


🎢 三、方法调用阶段(游玩过程)

对象创建后,可随时调用方法:

虚拟机执行顺序4.svg

示例方法

// 7. 实例方法 - 游玩项目 🎢
public void playGame(String gameName) {
    System.out.println(visitorBand + "正在玩【" + gameName + "】");
}
​
// 8. 静态方法 - 闭园统计 📊
public static void closePark() {
    System.out.println("🔚 闭园!今日游客总数:" + totalVisitors);
}

规则

  • 实例方法必须通过对象调用(需先有"游客手环")

  • 静态方法通过类名调用(直接找"园区管理处")


🎯 四、完整场景演示

public static void main(String[] args) {
    System.out.println("==== 游乐园启动 ====");
    // 首次触发类加载
    AmusementPark visitor1 = new AmusementPark("小明"); 
    visitor1.playGame("过山车");
    
    AmusementPark visitor2 = new AmusementPark("小红");
    visitor2.playGame("旋转木马");
    
    AmusementPark.closePark();
}

输出结果

==== 游乐园启动 ====
🎪 静态块:游乐园开园!
⏰ 开放时间:09:00
🛂 实例块:游客通过安检
🎉 构造器:欢迎小明!
🛂 实例块:游客通过安检
🎉 构造器:欢迎小红!
VIP-1623912000正在玩【过山车】
VIP-1623912005正在玩【旋转木马】
🔚 闭园!今日游客总数:2

执行时序图

虚拟机执行顺序5.svg


📚 五、关键规则总结表

元素

执行时机

执行次数

游乐园类比

静态常量

类加载(编译期确定)

1次

入园规则牌

静态变量

类加载(准备阶段赋默认值)

1次

中央游客计数器

静态块

类加载(按代码顺序)

1次

开园仪式

实例变量

对象创建(分配内存时)

每次new

游客专属手环

实例块

构造器之前执行

每次new

必经安检通道

构造器

对象创建最后一步

每次new

检票员欢迎

实例方法

对象创建后主动调用

任意次

游玩项目

静态方法

通过类名调用

任意次

园区广播/闭园通知


🧩 六、继承场景加餐(亲子游客通道)

父子类初始化顺序:

虚拟机执行顺序6.svg

示例

class Parent {
    static { System.out.println("👨 父类静态块"); }
    { System.out.println("👨 父类实例块"); }
    Parent() { System.out.println("👨 父类构造器"); }
}
​
class Child extends Parent {
    static { System.out.println("👶 子类静态块"); }
    { System.out.println("👶 子类实例块"); }
    Child() { System.out.println("👶 子类构造器"); }
}
​
// 输出顺序:
// 👨 父类静态块 → 👶 子类静态块 → 
// 👨 父类实例块 → 👨 父类构造器 → 
// 👶 子类实例块 → 👶 子类构造器

🚀 七、实战应用场景

  1. 静态块初始化全局配置(开园时准备物资):

public class ConfigLoader {
    public static final String API_KEY;
    
    static {
        // 从配置文件加载
        API_KEY = loadKeyFromFile(); 
    }
}
  1. 实例块统一验证(游客安检):

public class Rider {
    private int height;
    
    {
        if (height < 120) {
            throw new RuntimeException("❌ 身高不足120cm不能游玩");
        }
    }
}
  1. 静态常量定义配置(园区固定规则):

public class ParkRules {
    public static final int MAX_AGE = 70;
    public static final int MIN_HEIGHT = 110;
}

通过游乐园的完整生命周期,配合可视化流程图,Java类的加载顺序变得像游玩路线一样清晰!记住三个关键阶段:

  1. 静态准备 = 开园仪式(一次性)

  2. 对象创建 = 游客入园(按票入场)

  3. 方法调用 = 自由游玩(随时进行)

现在,你已经掌握了JVM加载的核心秘密!🎉

0

评论区