8

I have code

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) {
    ...
}

and I'm wondering how can it happen for IllegalStateException to be thrown. It apparently happened to a user of my app, but I'm not able to track what was wrong.

The documentation of Collection.addAll() says:

IllegalArgumentException - if not all the elements can be added at this time due to insertion restrictions

But what are the insertion restrictions?

I guess it depends on the exact type of the collection. I'm using ArrayList, so let's check docs for addAll() of List interface:

IllegalArgumentException - if some property of an element of the specified collection prevents it from being added to this list

Well, what element property could prevent the element to be added to the List? My both Collections are of the same type, I should be able to add null values..

Can anybody explain this to me, please?

Marcel Bro
  • 4,907
  • 4
  • 43
  • 70
  • I'm just shooting in the dark here, but might it not be connected to concurrency? – Mackiavelli Jul 22 '15 at 11:11
  • It's not entirely clear which version of Java you're using but the source code for Java SE 6 never throws that exception from `addAll()` except indirectly when accessing the `Collection`. Have you seen the stack trace and are you sure where the exception is thrown? – Persixty Jul 22 '15 at 11:25
  • 6
    Please add the stack trace of the exception to your question. – VGR Jul 22 '15 at 11:55
  • @VGR @DanAllen I'm using Java SE 7 and unfortunately don't have access to the stack trace. I found this piece of code in an app I'm working on, encapsulated in try catch block for `IllegalStateException` and was wandering how could that happen. – Marcel Bro Jul 22 '15 at 16:17
  • Unless the subFields.addAll line is the only line in that try-block, how can you be sure addAll is what caused the exception, without seeing the stack trace? – VGR Jul 22 '15 at 17:50

4 Answers4

1

Your code can never throw IllegalArgumentException because ArrayList#addAll cannot throw such exception.

In order to get that exception you have to use a class implementing Collection where such exception can be thrown. You could easily make your own by extending ArrayList and overriding involved methods.

Anonymous Coward
  • 3,140
  • 22
  • 39
  • 1
    A future implementation of `ArrayList#addAll` **could** throw an `IllegalArgumentException` (i.e. next version of jre). But of course this is pretty unlikely to happen. – slartidan Jul 22 '15 at 11:40
1

Depending on how much information you have from the user, this may be unanswerable. But I'll make a guess, and delete my answer if further evidence comes to light that contravenes it. :)

Assuming you wrote all the code, I agree that addAll() cannot throw IllegalStateException (and all the talk about IllegalArgumentException is irrelevant).

My guess is that the error does not originate from the addAll() call but from another call in the code (not shown) that attempts to manipulate one of these collections. It is possible to get an IllegalStateException by attempting to, for example, iterate through the list (using an iterator obtained with .iterator()) and remove an item, then attempt to remove another item without calling Iterator.next(). Similarly, Iterator.set() can throw one in an iterator obtained from an ArrayList. So my guess is, somewhere in manipulating the list, one of these things happens.

Alternatively, there are many ways that other collection implementations could throw one. So if we're not sure it pertained to the ArrayList, then we've got very little to go on.

David P. Caldwell
  • 3,394
  • 1
  • 19
  • 32
0

I'm not aware of any implementations (in the jre or any library) that throw an IllegalArgumentException.

But you could easily create your own implementation, that throws such an exception. The interface Collection makes the users aware, that an implementor could use an IllegalArgumentException - it does not say, that the implementors actualy do use it.

An example:

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();
    }

}

As a result I would recommend this approach:

  • check your code, that you are adding semantically reasonable items to your collection. Do not add objects of class Person to a list called postalCodes
  • handle any technical runtime exception in an appropriate way. For example rollback transactions, do logging, inform the user and/or the support team
  • consider to inform callers of your method (via JavaDoc), that your method could fail
slartidan
  • 20,403
  • 15
  • 83
  • 131
0

It does depend on the implementation. If you check the documentation for ArrayList, which is the actual class your using, you'll see this.

Throws: NullPointerException - if the specified collection is null

So your ArrayList should not throw the IllegalArgumentException. If you would use another implementation or a wrapper (see unmodifiable list, note that this example does not throw such an exception), it might throw such an exception.

So get the logging from your user and try to reproduce the issue.

Timo
  • 2,212
  • 2
  • 25
  • 46