【问题标题】:When does List.addAll() throw IllegalStateException?List.addAll() 什么时候抛出 IllegalStateException?
【发布时间】:2015-07-22 11:07:59
【问题描述】:

我有代码

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,所以让我们查看 addAll()List 接口的文档:

IllegalArgumentException - 如果指定集合的​​某个元素的某些属性阻止它被添加到此列表中

那么,什么元素属性可以阻止将元素添加到列表中?我的两个集合是同一类型的,我应该能够添加空值..

谁能给我解释一下?

【问题讨论】:

  • 我这里只是在暗处拍,会不会连接到并发?
  • 目前尚不清楚您使用的是哪个版本的 Java,但 Java SE 6 的源代码从不会从 addAll() 抛出该异常,除非在访问 Collection 时间接抛出异常。你看过堆栈跟踪,确定异常是在哪里抛出的吗?
  • 请将异常的堆栈跟踪添加到您的问题中。
  • @VGR @DanAllen 我正在使用 Java SE 7,但遗憾的是无法访问堆栈跟踪。我在我正在开发的一个应用程序中发现了这段代码,封装在 IllegalStateException 的 try catch 块中,并且正在徘徊怎么会发生这种情况。
  • 除非 subFields.addAll 行是该 try 块中的唯一行,否则您如何确定 addAll 是导致异常的原因,而不查看堆栈跟踪?

标签: java list add illegalargumentexception


【解决方案1】:

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

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

我的猜测是该错误并非源自 addAll() 调用,而是源自代码中的另一个调用(未显示),该调用试图操纵其中一个集合。 可以通过尝试遍历列表(使用通过.iterator() 获得的迭代器)并删除一个项目,然后尝试在不调用的情况下删除另一个项目来获得IllegalStateException Iterator.next()。同样,Iterator.set() 可以在从ArrayList 获得的迭代器中抛出一个。所以我的猜测是,在操纵列表的某个地方,会发生这些事情之一。

另外,other 集合实现可以通过多种方式抛出一个。因此,如果我们不确定它是否与 ArrayList 相关,那么我们就没有什么可做的了。

【讨论】:

    【解决方案2】:

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

    为了获得该异常,您必须使用一个实现 Collection 的类,在该类中可以抛出此类异常。您可以通过扩展 ArrayList 和覆盖涉及的方法轻松地制作自己的。

    【讨论】:

    • ArrayList#addAll 的未来实现可能抛出IllegalArgumentException(即 jre 的下一个版本)。但当然,这不太可能发生。
    【解决方案3】:

    它确实取决于实现。如果您检查the documentation 中的ArrayList,这是您实际使用的类,您会看到这一点。

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

    所以你的ArrayList 不应该抛出IllegalArgumentException。如果您要使用其他实现或包装器(请参阅unmodifiable list注意,此示例不会引发此类异常),它可能会引发此类异常。

    所以从您的用户那里获取日志并尝试重现问题。

    【讨论】:

      【解决方案4】:

      我不知道任何引发 IllegalArgumentException 的实现(在 jre 或任何库中)。

      但您可以轻松创建自己的实现,但会引发此类异常。 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),您的方法可能会失败

      【讨论】:

        猜你喜欢
        • 2011-03-22
        • 2011-11-10
        • 1970-01-01
        • 2011-10-27
        • 2021-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多