引言:卡在javac的20分钟
上周在迭代实景工程数据后端项目时,同事提交了一组工序状态相关的业务改动,本地执行mvn compile直接卡在javac阶段,终端光标闪了20分钟愣是没刷出半行错误日志。当时第一反应是Maven依赖冲突或者全量编译太慢,结果排查到最后发现是两处非常隐蔽的编译错误导致的——整个过程踩的坑和最终的修复思路,值得拿出来聊聊。
第一步:先确认阻塞点,别急着改代码
一开始我试图在报错代码上叠加修复,结果越改编译越慢,后来干脆回退到上一个干净的提交,只跑单模块编译:mvn -pl shigang-data-module compile,10秒就刷出了错误日志。
原本想用内部知识图谱快速对齐前后端字段,刚好当时知识图谱索引还没就绪,只能手动翻前端调用参数和后端接口定义,很快就找到了第一个明显的不一致点:后端qryStepInfo方法的返回值定义是Long类型,但前端传参和业务逻辑里都是按String处理的,返回的也是工序信息的JSON字符串,类型不匹配直接导致javac类型推断卡住。
踩坑实录:两个隐蔽错误差点让我绕路
修完类型问题后编译还是报错,这次是泛型方法引用的语法问题:补start/complete/updStepInfo业务逻辑时,我习惯性用了方法引用调用List的add方法,写法是list::add,但因为泛型擦除后编译期找不到对应的重载方法,直接报错。
这个坑非常典型:Java编译器的方法引用推断逻辑经常“抽风”,显式写lambda指定参数类型反而能通过编译,把list::add改成str -> list.add(str)后,编译错误直接消失。
这里放两段修复前后的代码对比,非常直观:
// 错误:返回值类型和业务逻辑不匹配
public Long qryStepInfo(String bizId) {
StepInfo stepInfo = getStepInfo(bizId);
return JSON.toJSONString(stepInfo); // 实际返回String,类型不匹配
}
// 修复后:类型和前后端对齐
public String qryStepInfo(String bizId) {
StepInfo stepInfo = getStepInfo(bizId);
return JSON.toJSONString(stepInfo);
}
// 错误:泛型方法引用编译不通过
List<String> stepList = new ArrayList<>();
stepList::add;
// 修复后:显式lambda指定参数类型
stepList.add(str -> stepList.add(str));
小步回退:别在错误基础上堆修复
修完这两处错误后,我一开始想顺手把重复的状态更新逻辑抽成私有方法,结果改的时候不小心引入了新的语法错误,编译又报错了。这时候我干脆回退到刚才的干净编译状态,只保留必要的类型修正和核心业务逻辑,再单独补新单测验证start/complete接口的行为,最后不仅编译通过,单测也全部跑通。
结尾:可带走的3个经验
- 编译卡住先跑单模块:全量编译慢还容易掩盖错误,直接切到报错模块跑单模块编译,10秒就能出错误日志,比等20分钟高效太多;
- 类型问题优先看前后端对齐:改后端返回值类型之前先翻前端的调用参数,别光改后端定义,不然前后端对不上还会出问题;
- 泛型问题直接改显式lambda:Java编译器的方法引用推断逻辑经常不按常理出牌,显式写lambda指定参数类型,能避免90%的泛型编译错误。

545

被折叠的 条评论
为什么被折叠?



