List.addAll() 什么情况下会抛出 IllegalStateException?

8

我有代码

private List<Field> subFields;
private Collection<Field> subFieldsCollection;

...

try {
    if (subFields == null && subFieldsCollection != null && !subFieldsCollection.isEmpty()) {
        subFields = new ArrayList<>();
        subFields.addAll(subFieldsCollection);
    }
} catch (IllegalStateException e) {
    ...
}

我在想如何会出现抛出IllegalStateException的情况。显然,我的应用程序的用户遇到了这个问题,但我无法追踪出错的原因。

Collection.addAll()的文档中说:

IllegalArgumentException - 如果由于插入限制,不能立即添加所有元素

但是插入限制是什么?

我猜这取决于集合的确切类型。我正在使用ArrayList,所以让我们查看List接口的addAll()文档:

IllegalArgumentException - 如果指定集合的某个元素属性阻止将其添加到此列表中,则为true

好吧,哪些元素属性可能会阻止元素被添加到列表中呢?我的两个集合都是相同类型的,我应该能够添加null值..

有人能向我解释一下吗?


我只是在瞎猜,但这可能与并发有关吗? - Mackiavelli
目前不太清楚您使用的是哪个版本的Java,但是Java SE 6的源代码在addAll()方法中从未直接抛出该异常,除非访问了Collection。您是否查看了堆栈跟踪并确定了异常抛出的位置? - Persixty
6
请在您的问题中添加异常的堆栈跟踪。 - VGR
@VGR @DanAllen 我正在使用Java SE 7,不幸的是我无法访问堆栈跟踪。我在我正在工作的应用程序中找到了这段代码,它被封装在try catch块中以捕获IllegalStateException异常,我想知道这是怎么发生的。 - Marcel Bro
除非subFields.addAll行是try-block中唯一的一行,否则如果没有查看堆栈跟踪,如何确定addAll是导致异常的原因? - VGR
4个回答

1

你的代码永远不会引发IllegalArgumentException,因为ArrayList#addAll不能抛出这样的异常。

为了获得该异常,你必须使用实现Collection接口的类,该类可能会抛出此异常。你可以轻松地通过扩展ArrayList并覆盖涉及的方法来创建自己的类。


1
ArrayList#addAll 的未来实现版本可能会抛出 IllegalArgumentException 异常(即 jre 的下一个版本)。但是当然,这种情况发生的可能性非常小。 - slartidan

1

根据您从用户那里获得的信息量,这可能无法回答。但我会猜测一下,如果有进一步证据与之相悖,我会删除我的答案。 :)

假设您编写了所有代码,我同意 addAll() 不能抛出 IllegalStateException(所有关于 IllegalArgumentException 的讨论都是无关紧要的)。

我猜测错误不是源自于 addAll() 调用,而是源自于代码中的另一个调用(未显示),它试图操作其中一个集合。例如,尝试通过迭代列表(使用 .iterator() 获取的迭代器)并删除一个项目,然后尝试在不调用 Iterator.next() 的情况下删除另一个项目,就可以得到 IllegalStateException。同样,从 ArrayList 获得的迭代器中,Iterator.set() 可以抛出异常。所以我猜测,在操作列表时,会发生其中一件事情。

或者,其他集合实现可能以许多方式引发异常。因此,如果我们不确定它是否适用于 ArrayList,那么我们几乎没有什么可依据的。


0

这取决于具体的实现。如果您查看 文档 中的 ArrayList,这是您正在使用的实际类,您将会看到以下内容。

抛出: NullPointerException - 如果指定的集合为 null

因此,您的 ArrayList 不应该抛出 IllegalArgumentException。如果您使用另一种实现或包装器(请参见 不可修改列表,请注意,此示例不会引发此类异常),则可能会引发此类异常。

因此,请从用户那里获取日志并尝试复现问题。


0

我不知道有任何实现(在jre或任何库中)会抛出IllegalArgumentException异常。

但是你可以轻松地创建自己的实现,以抛出这样的异常。接口Collection让用户意识到,实现者可能使用IllegalArgumentException - 它并没有说实现者实际上使用它。

一个例子:

import java.util.ArrayList;


public class PickyList<T> extends ArrayList<T> {

    public static class SpecialThing {

    }

    @Override
    public boolean add(T e) {
        if (e instanceof SpecialThing)
            return super.add(e);
        throw new IllegalArgumentException();
    }

}

因此,我建议采用以下方法:

  • 检查您的代码,确保将语义合理的项添加到集合中。不要将Person类的对象添加到名为postalCodes的列表中。
  • 适当的方式处理任何技术运行时异常。例如回滚事务、记录日志、通知用户和/或支持团队。
  • 考虑通过JavaDoc通知调用者,您的方法可能会失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接