导语
最近在做一个项目,该项目原来是由C++编写的,现在需要翻译成Java,在翻译过程中,同事没有理解清楚具体需求,在开发中进行了直译,直到生产上出现故障了(测试居然没测出来?)一起研究才发现...
需求
先看一下C++代码的样子
//vector& vCorBillGroups while(rs->next()){ if(load(rs,bill)){ //判断分组 corId = pm->getCorpId(bill.getPartyRoleId(),bill.getBillingCycleId()); if (corId < 0) throw BusinessLogicException("找不到银行划扣分组ID", corId); int i=0; for ( i=0;i
然后看一下同事翻译的第一版的样子
for (VirtualBillVO vo : bills) { long partyRoleId = vo.getPartyRoleId(); Partner partner = getPartnerManager().getPartner(Integer.parseInt(partyRoleId + "")); corId = partner.getCorpId(); if (corId < 0) { throw new BusinessLogicException("找不到银行划扣分组ID", corId); } int i = 0; for (CorBillGroupVO corVo : vCorBillGroups) { i++; if (corVo.getM_iCorperationId() == corId) { corVo.add(vo); break; } } if (i == vCorBillGroups.size()) { CorBillGroupVO corBillGroup = new CorBillGroupVO(); corBillGroup.setM_iCorperationId(corId); corBillGroup.add(vo); vCorBillGroups.add(corBillGroup); } }复制代码
分析
先不考虑这里具体是干啥的,单纯从代码结构的角度来看,似乎代码是没啥问题的。但是程序可不是看代码结构的! 由于C++代码有具体业务含义,简单介绍一下这段代码的背景:给一组账单(bills),按照运营商(corId)进行分组后返回。这么简单的需求,也不知道C++代码为啥写的这么复杂,这也导致翻译这段代码的同事犯了糊涂。
- 具体看C++: 循环账单列表,取账单的corId,i=0.循环分组vCorBillGroups,若分组里有该corId就将该账单添加到vCorBillGroups的第i个元素中,并跳出循环,判断i 和vCorBillGroups长度是否相等,若在前面循环中有break,i是不可能与vCorBillGroups的长度相等的(循环vCorBillGroups.size()次,每次i++,则当循环正常结束后,i肯定与vCorBillGroups.size()相等,若有break,则i肯定小于vCorBillGroups.size()了);若前面循环中没有break,说明该corId不在已经存在的组中,则添加到vCorBillGroups中。
- 再看同事翻译的Java:同样循环账单列表,但是采用了foreach的写法遍历,break条件满足之前就i++,那么在无break的时候是正常的,在有break的情况下就不一样了,例如vCorBillGroups.size() = 1 时,遍历一次vCorBillGroups,此时就算有break,i = 1,i ==vCorBillGroups.size();又会重新添加一次分组,那么就与C++代码的含义不一样了。
- 区别在哪里呢,仔细对比一下就会发现,两处代码的区别就在i++的使用上,for(;;i++)中,若for循环中有break,是不会进行++操作的,同事翻译时为了图方便,随意使用foreach,并将i++置于break条件之前,很明显无法起到控制作用了!
解决
最简单的解决方式就是如上述分析一样,将i++放在break条件之后即可,但是分组代码真的要写这么晦涩吗?见仁见智了...
总结
很少有人真的去注意for循环条件执行的顺序,以及i++和++i的区别,我老大在看到这段代码的时候也犹豫了一下,后来才恍然大悟怀疑这个i++在break之后是否有执行,测试了一下才确定自己的想法。平时这种代码可能都是不会有问题的,但是一旦触发了某种边界条件,就不一定是你想象的样子了。所以在写代码之前,还是要明确自己要实现的功能是什么,如果同事最开始翻译代码的时候明确知道这是一段分组代码,我相信他绝对不会这样去写的!