2

我偶尔会遇到一个非常奇怪的异常:

04-18 18:08:08.121:E/AndroidRuntime(3031):未捕获的处理程序:线程主因未捕获的异常而退出
04-18 18:08:08.141:E/AndroidRuntime(3031):java.lang.ArrayIndexOutOfBoundsException
04-18 18:08:08.141: E/AndroidRuntime(3031): at java.util.ArrayList.addAll(ArrayList.java:257)
04-18 18:08:08.141: E/AndroidRuntime(3031): at com.zigzagworld.text .formatter.FormatManager.formatIfNeeded(FormatManager.java:185)

这发生在 1.6 模拟器上。我的代码中调用的行addAll是:

mTasksAbove.addAll(schedule.above);

我唯一能想象的是某种并发访问mTasksAbove. 但是,我一直非常小心地确保所有访问都在同一个对象上同步。我唯一想到的另一件事是如果schedule.above在执行期间被修改addAll,但我相信这会生成一个ConcurrentModificationException(另外,我认为我的代码不会这样做)。有谁知道我应该寻找的其他东西?

编辑

根据 Raykud 的回答,我做了一点挖掘并找到了确切的错误。在 Android 1.6 源代码中,该addAll方法调用了一个内部方法,growAtEnd这是有缺陷的。这是源本身:

private void growAtEnd(int required) {
    int size = size();
    if (firstIndex >= required - (array.length - lastIndex)) {
        int newLast = lastIndex - firstIndex;
        if (size > 0) {
            System.arraycopy(array, firstIndex, array, 0, size);
            int start = newLast < firstIndex ? firstIndex : newLast;
            Arrays.fill(array, start, array.length, null);
        }
        firstIndex = 0;
        lastIndex = newLast;
    } else {
        int increment = size / 2;
        if (required > increment) {
            increment = required;
        }
        if (increment < 12) {
            increment = 12;
        }
        E[] newArray = newElementArray(size + increment);
        if (size > 0) {
            System.arraycopy(array, firstIndex, newArray, 0, size);
            /********************************************************\
            * BUG! The next 2 lines of code should be outside the if *
            \********************************************************/
            firstIndex = 0;
            lastIndex = size;
        }
        array = newArray;
    }
}

当列表先前已填充然后清空时,该错误抬起了丑陋的头,离开size == 0并且firstIndex == lastIndex > 0您尝试添加足够大的集合以使其不适合lastIndex当前数组大小。

从 2.2 开始,当该addAll方法被重写并growAtEnd从类中消失时,该错误就消失了。

谢谢雷库德的指点!

4

1 回答 1

1

从 1.5 开始,arraylist 中的方法 addAll 有问题,它应该在未来的发布中得到修复,但是我不确定是哪一个。要解决此问题,您可以为您的集合创建一个迭代器并逐个添加元素。这里有一个小代码可以提供帮助:

Iterator<MyTypeofObjectToAdd> e = myArrayListToCopyFrom.iterator();
    while (e.hasNext()) {
      arrayListToAdd(e.next());
    }

并且IndexOutOfBounds异常是因为您试图从没有任何内容的位置检索项目而引起的。

于 2012-04-18T23:17:42.083 回答