提供建立网站服务的公司,无水印视频素材下载免费网站,微信公众号怎么做好看,wordpress请求阿里java开发手册已经发表#xff0c;很多都值得认真研究思考#xff0c;看到零度的思考题#xff0c;没忍住研究了一下。在这里插入图片描述首先#xff0c;看一下给出的反例的执行结果。如果是1#xff0c;最后list中的元素为[2]如果把1很多都值得认真研究思考看到零度的思考题没忍住研究了一下。在这里插入图片描述首先看一下给出的反例的执行结果。如果是1最后list中的元素为[2]如果把1换成2会抛出ConcurrentModificationException异常为什么会出现这种情况这就要考察foreach的执行过程了。1. 代码编译foreach其实是一种语法糖通过简单明了的java语法实现相对复杂的功能通过查看代码编译之后的字节码文件可以看到foreach的循环会在编译期被转为迭代器(Iterator)的方式以下是反编译之后的代码ListString list Lists.newArrayList();
list.add(1);
list.add(2);
Iterator var2 list.iterator();
while(var2.hasNext()) {String num (String)var2.next();if(2.equals(num)) {list.remove(num);}
}//加入Java开发交流君样756584822一起吹水聊天2. ArrayList中的Iterator考察在ArrayList内部有一个Itr的内部类该内部类实现了Iterator接口通过ArrayList的iterator()函数获取到的就是内部类Itr的实例对象。内部类Itr的属性说明cursor下一个返回元素的索引lastRet上一个返回元素的索引如果没有就是默认值-1expectedModCount默认值是modCount(是AbstractList的属性表示集合结构发生变化的次数每次add或remove都会加1)从变量定义上就可以看出它是一个期望值用于在遍历的过程中查看ArrayList的结构有没有发生变化有点类似CAS的做法内部类Itr的主要函数说明hasNext()函数用于判断是否遍历到了集合的末尾return cursor ! size;checkForComodification()函数在next()和remove()函数中都会首先调用该方法来判断集合的结构是否发生变化如果结构发生了变化modCount就会加1不等于expectedModCount就会抛出异常if (modCount ! expectedModCount)throw new ConcurrentModificationException();next()函数先检查集合的结构有没有发生变化若是则抛出异常判断cursor有没有超过集合元素的个数判断cursor有没有超过ArrayList底层数组结构的大小若是则抛出异常cursor加1lastRet设置为当前返回元素的索引checkForComodification();
int i cursor;
if (i size)throw new NoSuchElementException();
Object[] elementData ArrayList.this.elementData;
if (i elementData.length)throw new ConcurrentModificationException();
cursor i 1;
return (E) elementData[lastRet i];
//加入Java开发交流君样756584822一起吹水聊天remove()函数lastRet判断是否小于0若是表示还未开始遍历集合迭代器当前的索引位于集合第一个元素之前判断元素的结构有没有发生变化通过ArrayList的remove函数去除lastRet索引位置的元素此时modCount加1cursor回退到lastRet的索引位置lastRet设为-1expectedModCount设置为当前modCount值if (lastRet 0)throw new IllegalStateException();
checkForComodification();
try {ArrayList.this.remove(lastRet);cursor lastRet;lastRet -1;expectedModCount modCount;
} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();
}//加入Java开发交流君样756584822一起吹水聊天结合代码分析反例条件为1.equals(num)的情况第一次循环使得cursor为1此时符合判断条件调用集合的remove函数删除元素modCount加1此时不等于expectedModCountsize减1变为1第二次循环调用hasNext函数此时cursor和size都为1判断集合中没有可遍历的元素遍历到了末尾结束循环集合中为2的元素是没有遍历到的最终打印出集合结果显示为[2]条件为2.equals(num)的情况第一次循环使得cursor为1此时不符合判断条件第二次循环hasNext调用后发现集合中还有元素继续遍历cursor为2此时符合判断条件调用集合的remove函数删除元素modCount加1此时expectedModCountsize减1变为1第三次循环hasNext函数调用的时候cursor为2大于size两者也不相等返回true继续执行循环体此时会调用next函数由于next函数首先会判断集合的结构有没有发生变化因为第二次循环中集合的结构已经变化了因此会抛出ConcurrentModificationException异常4. 为什么正例就不会出现这种问题因为删除元素调用的是迭代器的remove函数size变化的同时cursor也发生了变化不会出现cursor大于size的情况同时集合结构发生变化之后迭代器的remove函数中对expectedModCount重新设值感知到了结构的变化最后并发操作需要对迭代器加锁就不在此赘述了。