MinIO Java SDK 预签名URL生成与使用指南
记录使用 MinIO Java SDK 生成预签名 URL 的实践,包含下载和上传场景,以及一些容易出错的点。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-06-28 12:02:35 Java Stream Comparator NullPointerException IDEA调试
线上一个排序逻辑突然炸了,堆栈指着 Comparator.comparingInt 那一行,一看集合里有几个对象的排序字段是 null。
这种问题本地跑的时候不一定能马上发现,数据一多,null 值混进来,直接就 NPE。
原因很简单,Comparator.comparingInt 这类方法内部会调用键提取函数,如果函数返回 null,它尝试拆箱成 int 的时候就挂了。
同样地,用 comparing 然后链式调用 thenComparing 之类,哪个键提取返回了 null 都会炸。
比较稳妥的处理方式是用 Comparator.nullsLast 或 nullsFirst 包一层。比如:
result.sort(Comparator.comparing(
StatisticsVO::getFxjgmc,
Comparator.nullsLast(Comparator.comparingInt(fxjgmc -> FIXED_ORDER.indexOf(fxjgmc)))
));
这样 null 值会被统一放到列表末尾,不会再触发空指针。想要 null 排最前面就换成 nullsFirst。
如果不想用 nullsLast 那一套,也可以自己手动在键提取函数里做判断。比如我希望 null 值的排序权重最低,就返回 Integer.MAX_VALUE:
result.sort(Comparator.comparingInt(p -> {
if (p.getFxjgmc() == null) {
return Integer.MAX_VALUE;
}
return FIXED_ORDER.indexOf(p.getFxjgmc());
}));
其实就是让 null 映射到一个固定的远端位置,避免 compare 阶段碰到 null。
不过这种硬编码一个很大值的方式,如果业务里本来就有这种极值,可能会有冲突,但用作“排最后”的场景一般没问题。
Stream 操作里如果集合本身包含 null 元素,也可能在后续处理时出问题,最简单的办法就是先 filter 一遍:
List<String> filteredList = list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
别小看这一行,有时候集合是从外部接口或者数据库查出来的,到底有没有 null 自己很难完全控制,提前过滤能省很多事。
排序搞定了,调试的时候又碰到一个让人头疼的事:IDEA 里看集合变量,明明 size 显示有元素,但视图里 null 的位置直接不显示,仿佛不存在一样。这时候很容易误以为集合里没有 null,结果 NPE 照样出。
IDEA 的 Data Views 有个选项会隐藏 null 元素。可以到 Settings -> Build, Execution, Deployment -> Debugger -> Data Views -> Java,把 “Hide null elements in Collections” 的勾去掉。
如果用的是新版 IDEA,选项可能叫法有变化,留意类似的意思就行。还有一个 “Enable alternative view for Collections classes” 的选项,那个勾上之后会以更概括的方式展示集合内容,有时候也会让 null 的显示变得奇怪,调试排序问题时建议先关掉。
要是改完设置还是不显示,或者懒得去翻设置,最简单的就是打一行日志:
System.out.println("List content: " + result);
直接把整个集合打印出来,null 会变成字符串 "null" 显示在控制台,有没有一目了然。这种土办法在排查数据问题的时候其实最直接。
最后把排序和 null 处理揉在一起的写法,大概就是下面这样,既控制了 null 的顺序,又不会因为 null 导致排序中断:
result.sort(Comparator.comparing(
StatisticsVO::getFxjgmc,
Comparator.nullsLast(Comparator.comparingInt(fxjgmc -> {
if (fxjgmc == null) {
return Integer.MAX_VALUE;
}
return FIXED_ORDER.indexOf(fxjgmc);
}))
));
这里其实做了两层防护:外层 nullsLast 先把 null 从比较流程里摘出去,内层的键提取函数对值再做一个兜底,即使链条里某个环节逻辑有疏漏也不至于直接炸。
加上前面的调试设置,后面再碰到类似的排序需求,基本就不用半夜爬起来看报警了。
上一篇: Java Stream 排序与 Comparator 的空指针处理,以及 IDEA 调试里 null 不显示的坑
记录使用 MinIO Java SDK 生成预签名 URL 的实践,包含下载和上传场景,以及一些容易出错的点。
记录在 Aspose.PDF 里加载本地 TTF 字体,以及绕过 TTC 格式不支持问题的两种可行方案。
跑单测突然报 Command line is too long,大多数情况在 Run Configuration 里勾一个选项就完事。这里把原因和几种方案一起记一下。
记录 datetime 字段定义、插入、格式化查询以及 Java 端类型映射、时区等问题,避免线上踩坑。