双大括号初始化是利用匿名子类语法与实例初始化块快速初始化集合的技巧:外层大括号创建匿名子类,内层大括号为其实例初始化块;虽简洁但存在内存泄漏、序列化失败、类加载器负担等问题,现代java推荐使用list.of()等替代方案。

Java 中所谓的“双大括号初始化”(Double Brace Initialization)并不是匿名内部类的常规用法,而是一种利用匿名内部类语法 + 实例初始化块(Instance Initializer Block)实现集合或对象快速赋值的技巧。它看起来像用了两对大括号,但本质是:外层大括号定义一个匿名子类,内层大括号是该子类的实例初始化块。
第一对大括号:创建匿名子类
Java 允许用 new SomeClass() { ... } 语法创建某个类的匿名子类(或实现某个接口的匿名实现类)。比如 new ArrayList<string>() { ... }</string> 创建了 ArrayList 的一个匿名子类——注意,这本身不调用父类构造器以外的逻辑,只是继承。
第二对大括号:实例初始化块
在类定义体内(不在任何方法中)的一对 { ... } 是实例初始化块,会在每次构造对象时、构造器执行前自动运行。所以:
- 外层
new ArrayList<string>()</string>触发子类实例化 - 内层
{ add("a"); add("b"); }在该实例构造过程中执行,完成初始化
典型写法与实际效果
例如:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
List<string> list = new ArrayList<string>() {{
add("hello");
add("world");
}};
</string></string>
等价于手动写一个子类:
class MyList extends ArrayList<string> {
{
add("hello");
add("world");
}
}
List<string> list = new MyList();
</string></string>
注意事项和潜在问题
这种写法虽然简洁,但有明显缺点:
- 内存泄漏风险:匿名子类隐式持有外部类的引用(如果在非静态上下文中使用),可能导致外部实例无法被回收
-
序列化失败:匿名类默认不可序列化,若尝试序列化会抛
NotSerializableException - 类加载器负担:每次调用都生成新类,可能引发元空间(Metaspace)压力
-
不适用于 final 类:如
String、LocalDateTime等无法继承,不能用此方式初始化
现代 Java 更推荐使用 Arrays.asList()、List.of()(Java 9+)、Stream 或构造器 + builder 模式替代。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










