使用Guava Joiner.join()触发java.lang.NullPointerException问题排查
问题根源排查
从你的报错栈和代码来看,这个NullPointerException并不是因为args数组本身为null(你已经做了空检查),而是数组中存在null元素。
Guava的Joiner默认是严格校验模式:当你调用join()方法时,它会遍历数组中的每个元素,并用Preconditions.checkNotNull()强制校验元素非null——一旦遇到null,就会直接抛出NPE,这正好对应你报错栈里的com.google.common.base.Preconditions.checkNotNull这一行。
至于之前运行正常、近期突然触发的原因,大概率是:
- 你的输入数据发生了变化,现在传入的
args数组里出现了null元素; - 或者代码其他模块的逻辑修改,导致生成
args数组时混入了null值; - 你怀疑的依赖变化其实影响不大,Spigot 1.12.2打包的Guava版本本身就有这个严格校验的逻辑,只是之前没触发而已。
修复方案
根据你的需求(拼接数组、忽略指定位置元素,同时处理null),有几种靠谱的解决方式:
方式1:用Guava Joiner的null处理方法(最简洁)
直接给Joiner添加skipNulls()(跳过null元素)或者useForNull()(把null替换成指定字符串):
public static String join(String[] args, int ignored, String separator) { if (ignored > -1 && args != null) { // 补个args非null校验更稳妥 args = (String[]) ArrayUtils.remove(args, ignored); } // 方案A:跳过所有null元素 String combined = Joiner.on(separator).skipNulls().join(args); // 方案B:把null替换成空字符串(按需选择) // String combined = Joiner.on(separator).useForNull("").join(args); return combined; }
方式2:手动遍历处理(不依赖Guava)
如果不想依赖Guava的特性,也可以自己实现拼接逻辑,同时合并“忽略指定位置”和“过滤null”的逻辑,还能减少一次数组拷贝:
public static String join(String[] args, int ignored, String separator) { if (args == null) { return ""; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; i++) { // 跳过指定忽略的位置,同时跳过null元素 if (i == ignored || args[i] == null) { continue; } if (sb.length() > 0) { sb.append(separator); } sb.append(args[i]); } return sb.toString(); }
额外建议
- 可以在方法开头添加
args的空校验,避免传入null数组时的潜在问题; - 排查一下生成
args数组的上游逻辑,看看为什么会出现null元素,从源头避免可能更彻底。
内容的提问来源于stack exchange,提问作者Sage M
相关产品推荐
相关产品推荐

