You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中基于内部类的单例懒加载原理及LazyHolder加载时机问询

静态内部类单例的加载时机解析

代码示例

单例实现类

class Singleton {
    // 用于懒加载的私有静态内部类
    private static class LazyHolder {
        private static Singleton singleton = new Singleton();
    }

    public static Singleton getSingleton() {
        return LazyHolder.singleton;
    }
}

测试主类

class Main {
    // 修正原代码缺失的void关键字
    public static void main(String[] args) {
        Singleton s = Singleton.getSingleton();
    }
}

核心疑问

根据所学内容,private static Singleton singleton实例会在Singleton s = Singleton.getSingleton()语句执行时创建,但由于singleton是静态属性,我原本以为它会在LazyHolder类定义时就被创建。因此想明确:LazyHolder类实际何时被加载?是在Singleton类加载时(因为它是Singleton的内部类),还是在调用Singleton.getSingleton()方法时?同时需要了解运行时的具体执行过程。

加载时机与执行过程解析

  1. Singleton类的加载逻辑:当JVM首次遇到Singleton类的引用(比如Main类中调用getSingleton())时,会加载Singleton类,但此时不会自动加载它的静态内部类LazyHolder。Java规范明确规定:静态内部类属于外部类的“嵌套类”,不会随着外部类的加载而被加载,只有当它被主动引用时才会触发加载流程。

  2. LazyHolder类的触发节点:当调用Singleton.getSingleton()方法时,方法体内直接引用了LazyHolder.singleton,这属于对LazyHolder类的主动引用,此时JVM才会启动LazyHolder类的加载与初始化流程。

  3. singleton实例的创建逻辑:在LazyHolder类的初始化阶段,JVM会按顺序执行类的静态成员赋值语句,也就是private static Singleton singleton = new Singleton();,此时才真正创建Singleton的实例。这个初始化过程是线程安全的——JVM在类初始化阶段会保证静态成员的初始化操作是原子性的,且只会执行一次,这也是这种单例模式天生线程安全的核心原因。

  4. 完整运行流程:

    • 启动程序,JVM加载Main类;
    • 执行main方法中的Singleton s = Singleton.getSingleton();,首次引用Singleton类,JVM加载Singleton类;
    • 进入getSingleton()方法,代码访问LazyHolder.singleton,触发LazyHolder类的加载与初始化;
    • LazyHolder初始化时,创建Singleton实例并赋值给singleton静态变量;
    • 将singleton实例返回,赋值给Main类中的变量s。

内容的提问来源于stack exchange,提问作者idash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:53:32