Java 用什么方法?扩展集合<;字符串>;不适用于Set<;字符串>;
简短、自包含、不可编译的示例:Java 用什么方法?扩展集合<;字符串>;不适用于Set<;字符串>;,java,generics,Java,Generics,简短、自包含、不可编译的示例: public void test1() throws Exception { Map<String, Map<String, Set<String>>> a = Collections.singletonMap("One", Collections.singletonMap("Two", new HashSet<String>())); foo(a); } void foo(
public void test1() throws Exception {
Map<String, Map<String, Set<String>>> a = Collections.singletonMap("One",
Collections.singletonMap("Two", new HashSet<String>()));
foo(a);
}
void foo(Map<String, Map<String, ? extends Collection<String>>> x) {
}
public void test1()引发异常{
Map a=Collections.singletonMap(“一”,
Collections.singletonMap(“两个”,新的HashSet());
傅(甲),;
}
void foo(地图x){
}
收益率(JavaC1.8.0_102):
错误:不兼容类型:无法将映射转换为映射
傅(甲),;
^
我希望foo
可以采用Collection
的任何子类型,比如Set
或List
。上面的代码有什么问题吗?这将编译
void foo(Map<String, ? extends Map<String, ? extends Collection<String>>> x)
void foo(地图x)
按照您声明foo的方式,编译器需要一个确切类型的类型参数Map
。您可以将foo设置为通用:
<C extends Collection<String>> void foo(Map<String, Map<String, C>> x) {
}
void foo(地图x){
}
您的代码无法编译的原因与以下(更简单的)代码无法编译的原因相同:
List<Integer> l = Arrays.asList(1,2,3);
foo(l); //The method v(List<Object>) in the type Test is not applicable for the arguments (List<Integer>)
public void foo (List<Object> a){
...
}
这告诉编译器,foo
将接受扩展对象的内容列表,这就是List
的含义
在您的情况下,Map
不会扩展Map
即使您将foo
更改为void foo(Map x)
它也不会编译,因为Map
不会扩展Map
。他们是两种不同的类型
要使其工作,您可以将
foo
的签名更改为void foo(Map x)
。想解释一下原因吗?事实上,其他用户(+1)已经给出了一个,重复它是徒劳的。泛型不变性有时会产生影响。请注意,类型参数在签名中仅使用一次。这反映了一个事实,即类型参数不用于表示参数的类型、返回类型和/或抛出类型之间的任何类型的相互依赖关系。在缺乏这种相互依赖性的情况下,泛型方法被认为是糟糕的风格,而通配符是首选。(c) jls-4.5。1@user2418306我不明白如何仅使用通配符来进行等效的方法声明。请注意,我的解决方案比使用Map
更严格(更接近非编译代码)。例如,它不允许传递Map
。但是,很可能您实际上想要更通用的仅通配符版本。
List<Integer> l = Arrays.asList(1,2,3);
foo(l); //The method v(List<Object>) in the type Test is not applicable for the arguments (List<Integer>)
public void foo (List<Object> a){
...
}
public void foo (List<? extends Object> a){
...
}