3.5 第五层:组装线索,直达真相
为什么发生了异常呢?
如果说前四层是线索的话,真相其实已经隐藏在线索里面了。我带你梳理一下:
【第一层:异常信息解读】中说到
总结一下在foreach循环里面进行元素的remove/add操作抛出异常的真相:
因为foreach循环是Java的语法糖,经过编译后还原成了迭代器。
但是从经过编译后的代码的第26行可以看出,remove方法的调方是list,而不是迭代器。
经过前面的源码分析我们知道,由于ArrayList的"fail-fast"机制,调用remove方法会触发【modCount++】操作,对expectedModCount没有任何操作。只有调用迭代器的remove方法,才会维护expectedModCount=modCount。
所以调用了list的remove方法后,再调用Itr的next方法时,导致了expectedModCount!=modCount,抛出异常。
四.这题的坑在哪里?
前面讲了阿里开发手册。讲了在foreach循环里面进行元素的remove/add为什么会发生异常。有了这些铺垫之后。
4.1 回头再看
我们再回过头来看小马哥出的这个题:
我靠,这乍一看,foreach循环里面调用list.remove(obj)。我们刚刚分析过,会抛出ConcurrentModificationException异常。
你要这样答,你就进了小马哥的坑了。
这个题的坑在这三个点里面。小马哥并没有说这个list是ArrayList吧?如果你没有认真审题,先入为主的默认了这个list就是ArrayList。第一步就错了。
这是真正的高手,借力打力。借阿里开发手册的力,让你第一步就走错。
当使用CopyOnWriteArrayList的时候,程序正常执行。
4.2 还有一个骚操作
既然我们知道为什么会抛出异常,也知道怎么不抛出异常,List本来就是一个接口,那我们是不是可以实现这个接口,弄一个自定义的List呢?
比如下面的这个WhyTechnologyList,就是我自己的List,狸猫换太子,这操作,够"骚"啊。