Reputation: 133
Struggling with a generics issue using Guava's Multimap
class Foo{
...
private Multimap<Baz,? extends Bar> stuff;
...
public void overWriteStuff(Multimap<Baz,? extends Bar> newstuff){
this.stuff.clear();
this.stuff.putAll(newStuff);
}
}
This looks very straighforward to me, both stuff
and the argument newstuff
both have the same type yet I get a generics related compiler exception:
The method putAll(Multimap<? extends Baz,? extends capture#8-of ? extends Bar>) in the type
Multimap<Baz,capture#8-of ? extends Bar> is not applicable for the arguments (Multimap<Baz,capture#9-of ?
extends Bar>)
Can anyone see where my generics screw up is here?
Upvotes: 0
Views: 407
Reputation: 110046
The problem is that ? extends Bar
means "some specific (but unknown) subtype of Bar
". You don't know, for either the field in your class or for the parmater to your method, what actual type of values the multimap holds.
For example, if you have two classes Foo extends Bar
and Blah extends Bar
, you could assign a Multimap<Baz, Foo>
to stuff
and pass a Multimap<Baz, Blah>
to your method as newstuff
. If stuff.putAll(newstuff)
were allowed, you'd then have stuff
being a multimap that claims all of its values are instances of Foo
, when in fact some of them are instead instances of Blah
.
Perhaps you actually just want stuff
to be a Multimap<Baz, Bar>
? In that case its values can be any kind of Bar
and your method will work fine. Another option, as @rgettman mentions, is to introduce a type variable T extends Bar
to ensure that the values of stuff
and newstuff
are both the same subtype of Bar
; which you do depends on what you're actually trying to accomplish here.
Upvotes: 2
Reputation: 178263
The ?
wildcard from the original declaration cannot match the ?
wildcard from the parameter. They could be any subclass of Bar
(or Bar
itself), and they do not have to match.
You need to introduce a generic type parameter on Foo
to replace the wildcards, so that they will represent the same type.
class Foo<T extends Bar>{
In the variable declaration:
private Multimap<Baz, T> stuff;
And in the method parameter:
public void overWriteStuff(Multimap<Baz, T> newstuff){
Incidentally, this has everything to do with Java's generics but nothing to do with Guava. I could replicate the error with a Map
replacing the Multimap
.
Upvotes: 2