使用以下Java代码,是否有办法在第二级将集合与相关的通用参数组合在一起?:
public class Tester {
interface Base{};
class A implements Base{}
class B implements Base{}
@Test
public void test(){
Map<String, List<A>> a = new HashMap<String, List<A>>();
Map<String, List<B>> b = new HashMap<String, List<B>>();
Map<String, Base> bases = combine(a, b);
}
private Map<String, List<Base>> combine(Map<String, List<? extends Base>> one, Map<String, List<? extends Base>> two) {
Map<String, List<Base>> bases = new HashMap<String, List<Base>>();
bases.putAll(one);
bases.putAll(two);
return bases;
}
}
问题是combine()方法不会将Map<String, List<A>>
与Map<String, List<? extends Base>>
匹配,即使A扩展Base而bases.putAll()
也不会接受Map<String, List<? extends Base>>
的类型
答案 0 :(得分:3)
第一个问题,在combine()
中,您的bases
被声明为
Map<String, List<Base>>
但是试图放一个
Map<String, List<? extends Base>>
List<? extends Base>
不是List<Base>
的子类型,就像List<A>
不是List<Base>
的子类型一样。
要解决此问题,请将bases
中的combine
更改为
Map<String, List<? extends Base>> bases = new HashMap<String, List<? extends Base>>();
现在putAll
方法接受任何扩展List<? extends Base>
的类型。 List<? extends Base>
是List<? extends Base>
的子类型。
当你修复它时,你有另一个问题,你的combine
方法返回类型。它现在必须是
Map<String, List<? extends Base>>
以便它可以匹配bases
声明。
这会产生第三个问题。 Map<String, List<A>>
不是Map<String, List<? extends Base>>
类型参数的有效参数。您可以将参数更改为键入
Map<String, ? extends List<? extends Base>>
现在Map<String, List<A>>
可以作为参数传递。
最后,它看起来像
@Test
public void test() {
Map<String, List<A>> a = new HashMap<String, List<A>>();
Map<String, List<B>> b = new HashMap<String, List<B>>();
Map<String, List<? extends Base>> bases = combine(a, b);
}
private Map<String, List<? extends Base>> combine(
Map<String, ? extends List<? extends Base>> one,
Map<String, ? extends List<? extends Base>> two) {
Map<String, List<? extends Base>> bases = new HashMap<String, List<? extends Base>>();
bases.putAll(one);
bases.putAll(two);
return bases;
}
但老实说,你真的需要那么多级别吗?尽量让你的生活更轻松,如果可能的话,使用像Bohemian建议的那样。
答案 1 :(得分:1)
此处的问题是,对于通用,List<Subclass>
不是List<Superclass>
的实例。
要使代码生效,请将源地图的值类型更改为List<Base>
- 您仍然可以将A
和B
的实例添加到List<Base>
。
public void test() {
Map<String, List<Base>> a = new HashMap<String, List<Base>>();
Map<String, List<Base>> b = new HashMap<String, List<Base>>();
Map<String, List<Base>> bases = combine(a, b);
}
private Map<String, List<Base>> combine(Map<String, List<Base>> one, Map<String, List<Base>> two) {
Map<String, List<Base>> bases = new HashMap<String, List<Base>>();
bases.putAll(one);
bases.putAll(two);
return bases;
}
答案 2 :(得分:0)
考虑允许你在联合(...)
中做什么one.put("xxx", new ArrayList<B>());
这是有效的,因为声明是Map<String, List<? extends Base>>
。如果您被允许通过Map<String, List<A>>
,那么您可以混合类型。
如果您将参数更改为Map<String, ? extends List<? extends Base>>
,那么上面的示例不是有效的代码行,您将被允许将Map<String, List<A>>
传递给合并(..)。