静态代码块适合初始化复杂List,尤其当元素需多步构造、依赖外部资源或含逻辑判断时;它在类加载时执行一次,支持可变List、null元素、条件筛选及对象创建,并可通过Collections.unmodifiableList包装为不可变视图。

静态代码块适合初始化复杂 List,尤其当集合元素需多步构造、依赖外部资源或含逻辑判断时。直接在声明处用 Arrays.asList() 或双括号初始化虽简洁,但不支持 null 元素、不可变、且无法执行复杂逻辑——这时静态代码块是更稳妥的选择。
用 static 代码块构建可变、含逻辑的 List
静态代码块在类加载时执行一次,能灵活构造任意类型的 List(如 ArrayList),支持添加 null、重复元素、条件筛选、对象创建等操作。
- 声明一个 static final 的 List 引用(推荐用
private static final) - 在 static 块中 new 实例、逐个 add,或用循环/流处理数据源
- 若需不可变视图,最后用
Collections.unmodifiableList()包装
避免常见陷阱:线程安全与初始化时机
静态代码块本身是线程安全的(JVM 保证类初始化过程串行),但若块内调用了非线程安全方法(如手动修改共享集合、读取未同步配置),仍可能出问题。
- 不要在 static 块里调用可能抛异常的外部方法(如读文件、查数据库)——除非你明确捕获并处理,否则类加载失败会导致
NoClassDefFoundError - 确保所有依赖类已就绪;若 List 元素是自定义对象,其类必须已加载完成
- 避免在块中引用尚未初始化的其他 static 字段(除非已声明在前)
实用示例:初始化带业务逻辑的用户列表
比如要预置一组测试用户,其中部分字段需计算、部分需过滤:
立即学习“Java免费学习笔记(深入)”;
public class UserConfig {
private static final List<User> USERS;
static {
List<User> list = new ArrayList<>();
list.add(new User("Alice", 25, "alice@example.com"));
list.add(new User("Bob", 30, "bob@example.com"));
// 过滤掉邮箱为空的用户(假设构造后可能设为 null)
list.removeIf(user -> user.getEmail() == null);
// 对年龄做统一修正
list.forEach(user -> user.setAge(user.getAge() + 1));
USERS = Collections.unmodifiableList(list);
}
}
替代方案对比:什么时候不用 static 块?
如果 List 结构简单、元素固定且无副作用,优先考虑更轻量的方式:
- 静态工厂方法:语义清晰,支持泛型推导,便于单元测试 mock
- Enum + values():适合枚举型常量集合,天然线程安全、不可变
- ServiceLoader 或配置中心加载:运行时动态初始化,更适合可配置场景


















