小枫听到这个面试题的时候,心想这是什么水面试官,怎么问这么简单的题近视不戴眼镜会怎么样目,心想一个for循环加上equal判断再删除不就完事了吗?但是转念一想,不对,这里面肯定有陷阱,不然不会问这么看似简单的问题。小枫突然想起来之前写代码的时候好像遇到过这个问题,也是在arraylist中删除指定元素,但是直接for循环remove元素的时候还抛出了异常,面试官的陷阱估计在这里。小枫暗自窃喜,找到了面试官埋下的陷阱。 小枫回想起当天的的测试情况,代码进行了脱敏改造。当初是要在arraylist中删除指定元素,小枫三下五除二,酣畅淋漓的写下了如下的代码,信心满满的点了run代码的按钮,结果尴尬了,抛异常了。
一个大大红色的异常马上就出来了,omg,怎么会这样呢,感觉代码没什么问题啊,赶紧看看抛了什么异常,在哪里抛的异常吧。可以看出来抛最美的逆行者了一个concurrentmodificationexception的异常,而且是在itr这个类中的一个检测方法中抛出来的异常,这是怎么回事呢?我们的原始代码中并没有这个itr代码,真是百思不得其解。
既然从源代码分析不出来,我们就看下源代码编译后的class文件中的内容是怎样的吧,毕竟class文件才是jvm真正执行的代码,不看不知道,一看吓一跳,jdk原来是这么玩的。原来如此,我们原始代码中的for-each语句,编译后的实际是以迭代器来代替执行的。
通过arraylist创建的itr这个内部类迭代器,于是for-each循环就转化成了迭代器加while循环的方式,原来看上去的for-each循环被挂羊头卖狗肉了。
itr这个内部类迭代器,通过判断hasnext()来判断迭代器是否有内容,而next()方法则获取迭代器中的内容。
大致的过程如下所示:
真正抛异常的地方是这个检测方法, 当modcount与expectedmodcount不相等的时候直接抛出异常了。那我们要看下modcount以及expectedmodcount分别是什么。这里的modcount代表arraylist的修改次数,而expectedmo英语美文dcount代表的是迭代器的修改次数,在创建itr迭代器的时候,将modcount赋值给了expectedmodcount,因此在本例中一开始modcount和expectedmodcount都是4(添加了四次string元素)。但是在获取到b元素之后,arraylist进行了remove操作,因此modcount就累加为5了。因此在进行检查的时候就出现了不一致,最终导致了异常的秤的组词产生。到此我们找到了抛异常的原因,循环使用迭代器进行循环,但是操作元素却是使用的arraylist操作,因此迭代器在循环的时候发现元素被修改了所以抛出异常。
我们再来思考下,为什么要有这个检测呢?这个异常到底起到什么作用呢?我们先来开下concurrentmodificationexception的注释是怎么描述的。简单理解就是不允花的学校课文分析许一个线程在修改集合,另一个线程在集合基础之上进行迭代。一旦检测到了这种情况就会通过fast-fail机制,抛出异常,防止后面的不可知状况。
既然抛异常的原因是循环使用了迭代器,而删除使用arraylist导致检测不通过。那么我们就循环使用迭代器,删除也是用迭代器,这样就可以保证一致了。
本文主要对于arraylist在for循环中进行元素删除出现的异常进行源码分析,这也是面试的时候经常出现的面试陷阱题,面试官通过这样看似简单的题目考察候选者的jdk源码的掌握程度。
真正的大师永远怀着一颗学徒的心
到此这篇关于java面试必备之arraylist陷阱解析的文章就介绍到这了,更多相关java arraylist内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-05 21:25:15,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/a7b870602438e81eaed34578cac46f39.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Java面试必备之ArrayList陷阱解析.doc
本文 PDF 下载地址:Java面试必备之ArrayList陷阱解析.pdf
留言与评论(共有 0 条评论) |