使用Guava的Multimap解决了泛型问题
class Foo{
...
private Multimap<Baz,? extends Bar> stuff;
...
public void overWriteStuff(Multimap<Baz,? extends Bar> newstuff){
this.stuff.clear();
this.stuff.putAll(newStuff);
}
}
对我来说这看起来非常简单,stuff
和参数newstuff
都有相同的类型,但我得到了与泛型有关的编译器异常:
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>)
有人能看到我的仿制品搞砸了吗?
答案 0 :(得分:2)
原始声明中的?
通配符与参数中的?
通配符不匹配。它们可以是Bar
(或Bar
本身)的任何子类,并且它们不必匹配。
您需要在Foo
上引入泛型类型参数来替换通配符,以便它们代表相同的类型。
class Foo<T extends Bar>{
在变量声明中:
private Multimap<Baz, T> stuff;
在方法参数中:
public void overWriteStuff(Multimap<Baz, T> newstuff){
顺便说一句,这与Java的泛型有关,但与Guava无关。我可以使用Map
替换Multimap
来复制错误。
答案 1 :(得分:2)
问题在于? extends Bar
表示&{34>某些特定的(但未知)Bar
&#34;的子类型。您不知道,对于您班级中的字段或您方法的参数,您可以知道多图包含的实际值类型。
例如,如果您有两个类Foo extends Bar
和Blah extends Bar
,则可以将Multimap<Baz, Foo>
分配给stuff
并将Multimap<Baz, Blah>
传递给您的方法, newstuff
。如果允许stuff.putAll(newstuff)
,那么您stuff
是一个多图,声称其所有值都是Foo
的实例,而实际上其中一些是Blah
的实例{1}}。
也许你真的只想让stuff
成为Multimap<Baz, Bar>
?在这种情况下,它的值可以是任何类型Bar
,您的方法将正常工作。正如@rgettman所提到的,另一个选择是引入一个类型变量T extends Bar
,以确保stuff
和newstuff
的值都是{em>相同的子类型{ {1}};你做的取决于你在这里实际想要完成的事情。