Reputation: 76057
in the following snippet:
package test;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
public class WildcardsTest<K, V> {
private Iterator<Map.Entry<K, ? extends Collection<V>>> iterator;
public WildcardsTest(Map<K, ? extends Collection<V>> map) {
iterator = map.entrySet().iterator();
/* Type mismatch: cannot convert from
Iterator<Map.Entry<K,capture#1-of ? extends Collection<V>>> to
Iterator<Map.Entry<K,? extends Collection<V>>> */
}
}
The assignment is incorrect, although the types seem to match exactly.
I've devised a dirty workaround by specifying the type of the Collection as another generic parameter, like this:
public class WildcardsTest<K, V, C extends Collection<V>> {
private Iterator<Map.Entry<K, C>> iterator;
public WildcardsTest(Map<K, C> map) {
iterator = map.entrySet().iterator();
}
}
But that C
parameter is really a "don't care" type that only complicates the API, is there any way to get rid of it while maintaining type safety?
Thanks.
Upvotes: 3
Views: 2050
Reputation: 298818
Do it like this and it will work:
private final Iterator<? extends
Map.Entry<K, ? extends Collection<V>>
> iterator;
You can still use the iterator like this:
public void foo(){
while(iterator.hasNext()){
Entry<K, ? extends Collection<V>> entry = iterator.next();
Collection<V> value = entry.getValue();
}
}
For reference, read the get and put principle (originally from Java Generics and Collections)
Upvotes: 4
Reputation: 420921
The assignment is incorrect, although the types seem to match exactly.
The two ?
-wildcards can be bound to two different classes. Put it this way, it is quite obvious that there is a type mismatch:
private Iterator<Map.Entry<K, ArrayList<V>>> iterator;
public WildcardsTest(Map<K, HashSet<V>> map) {
iterator = map.entrySet().iterator();
}
When you introduce the C
, you "force them" to refer to the same class.
Upvotes: 2