博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
i++引发的惨案
阅读量:5903 次
发布时间:2019-06-19

本文共 2399 字,大约阅读时间需要 7 分钟。

导语

最近在做一个项目,该项目原来是由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之后是否有执行,测试了一下才确定自己的想法。平时这种代码可能都是不会有问题的,但是一旦触发了某种边界条件,就不一定是你想象的样子了。所以在写代码之前,还是要明确自己要实现的功能是什么,如果同事最开始翻译代码的时候明确知道这是一段分组代码,我相信他绝对不会这样去写的!

转载于:https://juejin.im/post/5ba47786e51d4539701e4334

你可能感兴趣的文章
前端基础入门一(HTML)
查看>>
出现:意外的预编译头错误,只需重新运行编译器就可能修复此问题
查看>>
再不努力,就真的没有机会了
查看>>
SVN Hooks的介绍及使用
查看>>
【Demo】HTML5 拍照上传
查看>>
路由器设置密码和标语
查看>>
CSS3属性
查看>>
Oracle 字符集的查看和修改【上】
查看>>
JQuery 基础操作
查看>>
OSPF 精髓 5类LSA 和RIP综合实验
查看>>
nginx缓存设置
查看>>
linux 脚本之 expect命令使用
查看>>
Java面向对象基础
查看>>
Fedora 安装fcitx输入法
查看>>
沃通SSL证书支持ECC算法吗?
查看>>
javassist用法总结
查看>>
求dojo/domReady不能在sync loader下使用的原因
查看>>
全球域名商(国际域名)解析量排行榜TOP20(6月9日)
查看>>
好程序员web前端分享CSS3弹性盒
查看>>
游戏UI框架设计(二) : 最简版本设计
查看>>