分析阿里开发手册的foreach中remove/add反例

先附上阿里手册原文截图:

172637_OE0z_3760288.png

ok,故事开始了:

  1. 反例贴到IDE,在for后加上sysout(a), run一下,打印结果正确,没有任何问题;
  2. 把“1”改成“2”,看起没问题三,run一下

18182526_QHjS.jpg

173410_PTnK_3760288.png

3.以checkForComodification关键字,百度一番,收获如下:

  • checkForComodification()方法,主要就是检测modCount == expectedModCount ;
  •  expectedModCount 是在Itr中定义的:int expectedModCount = ArrayList.this.modCount;所以他的值是不可能会修改的,所以会变的就是modCount。
  • ArrayList中无论add、remove、clear方法只要是涉及了改变ArrayList元素的个数的方法都会导致modCount的改变。

所以:

  • 由于最开始add了2次,modCount =2;
  • 进入foreach时,迭代器初始化了expectedModCount为2;
  • for 里面remove了“2”,所以modCount+1,变为3,此时expectedModCount 不等于modCount了

似乎明白了,但是为什么remove“1”可以呢?关键时刻还是得靠跟踪源码:

迭代器有个游标cursor,移除2的时候,由于2是第二个元素,此时cursor为2。移除了“2”之后list的size变成了1,然后再进行for迭代的时候,先调用了hasnext判断是否到末尾,这货是这么判断的174929_qGlc_3760288.png

。。。。。。。(此处省略一万字)

此时显然不相等,所以它以为还有next,所以调用了next方法

175014_OD4d_3760288.png然后就在这里就悲剧的抛异常了..

也许没仔细看异常,还想当然的以为是remove的时候抛异常的,再看一下异常堆栈,没错,是remove成功后,再尝试迭代抛异常了...

OK,如果是remove“1”呢?

移除“1”时,cursor为1,而移除后,list中只有“2”,故size为1,所以hasnext返回了false,然后就没有然(异)后(常)了。。

也就是说,这个反例,只要在foreach中移除的不是倒数第二个元素就会报错,只有倒数第二个元素被移除的时候,移除后再循环时hasnext才会返回false;否则hasnext为true,进入next时报错。

for下标、iterator则可以,foreach不行。

所以,不要在foreach循环中做列表增删

 

转载于:https://my.oschina.net/u/3760288/blog/1797443

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值