Reputation: 9
I have a problem related to JAVA wildcards and generics. I do not want to post my own complex code, so I will use the Collection
interface for demonstration:
Collection<String> stringCollection = new HashSet<String>();
stringCollection.add("1");
stringCollection.add("2");
stringCollection.add(stringCollection.iterator().next());
Here, the last line is no problem. add()
requires a string and next()
returns a string.
But:
Collection<?> anyCollection = stringCollection;
anyCollection.add(anyCollection.iterator().next());
Using the wildcard, Eclipse tells me the error
The method add(capture#19-of ?) in the type Collection is not applicable for the arguments (capture#20-of ?)
But why? I need to use the wildcarded Collection. Somehow Eclipse just doesn't get that next()
definitely MUST return an object exactly of the type add()
requires.
Is there any way to fix this without getting an error? For sure, a cast to (capture#20-of ?)
doesn't work.
Upvotes: 0
Views: 955
Reputation: 110084
You can't add anything but null
to a Collection<?>
. Yes, you know that any element that's already in the collection should be able to be added to it, but the type doesn't reflect that. <?>
and <? extends Foo>
should only be used when you only need to retrieve objects from the collection and not add to it. Can you show why you need to use a wildcard as opposed to, say, Collection<E>
?
(I assume you know this, but in your example your collection is a Set
and as such, adding any element that's already in it will do nothing.)
Edit:
From your comment, it sounds to me like you don't want a wildcard but just a generic method:
public <T extends PersistenceObject> void doSomething(Dao<T> dao) {
T o = dao.createNew();
// ...
dao.save(o);
}
The same would be true of a method that wants to re-add the first element of a Collection
to it:
public <E> boolean reAddFirst(Collection<E> collection) {
return collection.add(collection.iterator().next());
}
The specific type parameter (rather than a wildcard) tells the compiler that the type retrieved from the object is the same type that the object expects to be passed to its method.
Upvotes: 4
Reputation: 4715
Make anyCollection collection of Object
Collection<Object> anyCollection = stringCollection;
This should work
Upvotes: 0
Reputation: 24801
You can't add a string object in to a collection of type Collection<?>
, because the type Collection itself means that you dont know the type of the collection, hence the compiler won't allow you to add arbitrary types in it.
One way to fix this is to cast it like so:
Collection<?> c = new HashSet<String>();
Collection strCol = (Collection<String>)c;
strCol.add("Suraj");
Upvotes: 0