二次调用类后实例初始化器不可达,静态List调用后为空问题排查
兄弟,你这问题绝对是踩了**双大括号初始化(Double Brace Initialization)**的坑!我之前也栽过这个跟头,给你掰扯清楚:
为啥你的代码会出问题?
先看你写的这段初始化代码:
new ArrayList<String>(){{ add("abject"); ... }}
这写法看着简洁,本质上是创建了ArrayList的匿名子类,然后用实例初始化块(就是那对大括号里的代码)来添加元素。但把它赋值给static final静态变量时,就会触发几个致命问题:
1. 初始化顺序与失败风险
静态变量是在类加载阶段初始化的,但双大括号里的add代码是实例初始化逻辑——只有创建匿名子类实例时才会执行。如果类加载过程中,这个匿名子类的初始化出了岔子(哪怕是极小的异常,比如某种你没注意到的字符问题),JVM会直接标记这个类为「初始化失败」:
- 首次调用时,可能列表还没完成初始化就被返回,导致为空;
- 二次调用时,JVM不会再尝试初始化这个类了,直接抛出错误,看起来就是「实例初始化器不可达」。
2. 外部修改风险
你直接返回了原List的引用,要是调用方不小心执行了clear()或者remove()操作,原列表直接就空了!这也是很多人忽略的点——可变集合直接对外暴露太危险。
替换方案:安全又靠谱的写法
赶紧把双大括号初始化换掉,给你几个不同版本的方案:
方案1:Java 9+ 用List.of()(最简洁)
如果你的项目用Java 9及以上,直接用官方提供的不可变集合:
private static final List<String> abasicWordList = List.of( "abject", "aberration", "abjure", "abnegation", "abrogate", "abscond", "abstruse", "accede" ); public static List<String> getabasicWordList() { return abasicWordList; // List.of()返回的是不可变列表,不怕被修改 }
方案2:Java 8及以下 用静态初始化块+不可变包装
兼容性拉满的写法,还能防止外部修改:
private static final List<String> abasicWordList; static { List<String> tempList = new ArrayList<>(); tempList.add("abject"); tempList.add("aberration"); tempList.add("abjure"); tempList.add("abnegation"); tempList.add("abrogate"); tempList.add("abscond"); tempList.add("abstruse"); tempList.add("accede"); abasicWordList = Collections.unmodifiableList(tempList); } public static List<String> getabasicWordList() { return abasicWordList; }
用static块初始化是标准的静态变量初始化方式,类加载时一定会执行完成;Collections.unmodifiableList()把列表包装成不可变的,调用方没法修改原数据。
方案3:Java 8 也可以用Arrays.asList()+不可变包装
稍微简洁一点的写法:
private static final List<String> abasicWordList = Collections.unmodifiableList( Arrays.asList("abject", "aberration", "abjure", "abnegation", "abrogate", "abscond", "abstruse", "accede") ); public static List<String> getabasicWordList() { return abasicWordList; }
注意:Arrays.asList()返回的列表是固定大小的(不能添加/删除),但可以修改元素,所以一定要用unmodifiableList()包装成完全不可变的。
总结一下
双大括号初始化看着酷,但坑太多:创建匿名子类、持有外部类引用容易内存泄漏、初始化逻辑不稳定、可读性差。换成标准的静态初始化或者官方提供的不可变集合写法,既能解决你现在的问题,还能避免后续踩更多坑。
内容的提问来源于stack exchange,提问作者HatmanStack

