Java ArrayList.Itr#next()何时会在此行抛出ConcurrentModificationException?

Java ArrayList.Itr#next()何时会在此行抛出ConcurrentModificationException?,java,arraylist,iterator,Java,Arraylist,Iterator,这个问题是关于JDK1.8.0_74的。该类是java.util.ArrayList$Itr。调用ArrayList\iterator()方法时,将返回此(内部)类的实例。具体来说,我的问题是关于Itr上的next()方法: 850 public E next() { 851 checkForComodification(); 852 int i = cursor; 853 if (i >= size) 854

这个问题是关于JDK1.8.0_74的。该类是
java.util.ArrayList$Itr
。调用
ArrayList\iterator()
方法时,将返回此(内部)类的实例。具体来说,我的问题是关于
Itr
上的
next()
方法:

850        public E next() {
851            checkForComodification();
852            int i = cursor;
853            if (i >= size)
854                throw new NoSuchElementException();
855            Object[] elementData = ArrayList.this.elementData;
856            if (i >= elementData.length)
857                throw new ConcurrentModificationException();
858            cursor = i + 1;
859            return (E) elementData[lastRet = i];
860        }
我理解
checkForComodification
call on line#851的基本原理[1]。我也理解第853行的
(I>=size)
检查[2]

但是,检查
如果(i>=elementData.length)
在线#856在防范什么情况呢?

在单线程代码中,我无法使用在线的
ConcurrentModificationException
使某些代码失败

[1] :迭代器创建失败后的结构修改:

static void coMod() {
        ArrayList<Integer> list = new ArrayList<>(4);
        list.add(1);
        list.add(2);
        Iterator<Integer> itr = list.iterator();
        list.remove(0); //structural modification after iterator creation
        if (itr.hasNext()) {
            System.out.println("wait, there's more!");
            itr.next(); // modification while iterating -- 
                        // fails at java.util.ArrayList$Itr.next(ArrayList.java:851)
        }
    }
static void coMod(){
ArrayList=新的ArrayList(4);
增加第(1)款;
增加(2);
迭代器itr=list.Iterator();
list.remove(0);//迭代器创建后的结构修改
if(itr.hasNext()){
System.out.println(“等等,还有更多!”;
itr.next();//迭代时的修改--
//在java.util.ArrayList$Itr.next处失败(ArrayList.java:851)
}
}
[2] :迭代器到达末尾后失败

static void noHasNext() {
    ArrayList<Integer> list = new ArrayList<>(4);
    Iterator<Integer> itr = list.iterator();
    itr.next(); // unguarded next call -- 
                // fails at java.util.ArrayList$Itr.next(ArrayList.java:854)
}
static void noHasNext(){
ArrayList=新的ArrayList(4);
迭代器itr=list.Iterator();
itr.next();//未防护的下一个调用--
//在java.util.ArrayList$Itr.next处失败(ArrayList.java:854)
}

这是只有在多线程情况下才会发生的情况

我相信线程1必须在执行第855行之前立即停止。线程2将出现并将ArrayList.this.elementData设置为一个新的(较小的)数组


与ArrayIndexOutOfBoundsException异常相比,提供更好的异常是一种廉价的检查,否则会抛出该异常。从理论上讲,优化器甚至可能检测到正在显式检查的数组边界,而忽略对ArrayIndexOutOfBoundsException的检查。

这是仅在多线程情况下才会发生的情况

我相信线程1必须在执行第855行之前立即停止。线程2将出现并将ArrayList.this.elementData设置为一个新的(较小的)数组


与ArrayIndexOutOfBoundsException异常相比,提供更好的异常是一种廉价的检查,否则会抛出该异常。理论上,优化器甚至可能检测到正在显式检查的数组边界,而忽略对ArrayIndexOutOfBoundsException的检查。

“在单线程代码中”-这可能是这里的重要因素…我明白了,但是
ArrayList
不是线程安全的;那么它需要进行检查吗?这只是一个调试道具-事实上,它甚至在这里的Javadoc简介中提到:如果元素数组通过从另一个线程添加而增长,
size
的新值会传播到调用
next
的线程,但该线程仍会看到
ArrayList的旧值。这个.elementData
。。。?听起来有些牵强,但这是我能想到的最好的方法。“在单线程代码中”-这可能是这里的重要因素…我明白了,但是
ArrayList
不是线程安全的;那么它需要进行检查吗?这只是一个调试道具-事实上,它甚至在这里的Javadoc简介中提到:如果元素数组通过从另一个线程添加而增长,
size
的新值会传播到调用
next
的线程,但该线程仍会看到
ArrayList的旧值。这个.elementData
。。。?对我来说,这听起来有些牵强,但这是我能想到的最好的办法。这并不是说“这是一种只能在多线程情况下发生的事情”。@LewBloch解释了它是如何在单线程情况下发生的。问题是在第857行(而不是一般情况下)抛出异常的具体时间。checkForComodification()是对修改的常规(单线程)检查。并非“这是仅在多线程情况下才会发生的事情”。@LewBloch解释了它如何在单线程情况下发生。问题是在第857行(而不是一般情况下)抛出异常的具体时间。checkForComodification()是修改的常规(单线程)检查。