延迟初始化是java中推迟高开销对象创建时机的优化技术,核心为首次访问时才初始化,以节省启动时间与内存;静态变量推荐静态内部类holder模式,实例变量常用volatile+双重检查锁定。

Java 中没有“延迟绑定”这个标准术语,你实际想问的很可能是延迟初始化(Lazy Initialization)——即变量在首次被访问时才创建和赋值,而不是在声明时或类加载时就完成初始化。
延迟初始化的核心目的
它不是为了“绑定”,而是为了推迟高开销对象的创建时机,从而节省启动时间、内存资源,或规避初始化依赖循环。比如:一个数据库连接池、大型缓存对象、或需读取配置文件才能构建的服务实例。
关键前提:该变量不是所有路径都必然用到;若每次都会访问,延迟反而增加判断开销,得不偿失。
静态变量的推荐方式:静态内部类 Holder 模式
这是最简洁、线程安全、且无同步开销的方案,利用 JVM 类初始化的天然同步机制:
- 声明一个私有静态内部类,其中定义 static final 字段并直接初始化
- 提供一个 public static 方法,仅返回该内部类的字段
- JVM 保证:内部类仅在首次调用该方法、且真正访问其字段时才触发初始化(
<clinit></clinit>)
示例:
static final Config instance = new Config();
}
public static Config getConfig() {
return ConfigHolder.instance;
}
实例变量的常用方式:双重检查锁定(DCL)
适用于非静态字段,必须配合 volatile 修饰符防止指令重排序,确保其他线程看到的是完全构造好的对象:
- 先检查是否为 null(无锁)
- 若为 null,则加锁再检查一次(避免重复初始化)
- 在 synchronized 块内完成 new 实例 + 赋值
示例:
private volatile ExpensiveService service;public ExpensiveService getService() {
if (service == null) {
synchronized (this) {
if (service == null) {
service = new ExpensiveService();
}
}
}
return service;
}
什么时候不该用延迟初始化
它不是银弹。以下情况应优先选择普通初始化(即声明时直接 new 或调用工厂方法):
- 对象构造成本很低(如简单 POJO、空集合)
- 该字段在绝大多数使用场景中都会被访问
- 初始化逻辑本身依赖外部状态,且该状态可能随时间变化(延迟后行为不可预期)
- 代码可读性和维护性比微秒级性能更重要(延迟初始化会增加理解成本)
记住:JVM 对普通 final 字段的初始化已有强保障,无需手动干预;延迟初始化是主动打破这种便利,只为换取特定收益。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











