2 回答
TA贡献1830条经验 获得超9个赞
正如您在问题中途似乎意识到的那样,您的问题不在于List<Ps>
与PsList
.
问题是你不能添加到Map<String, ? extends List<Ps>>
.
让我们考虑一个更简单的例子:
void doSomething(Map<String, ? extends Number> map) { map.put(String, Integer.valueOf(0)); // Not allowed.}
问题在于,这Map<String, ? extends Number>
并不意味着“值可以是 Number 或 Number 的任何子类”。
每个通用类型对象都有一个特定的非通配符类型。意思是,不存在类型为 的 Map Map<String, ? extends Number>
。然而,以下情况可能存在:
Map<String, Integer>
(仅允许整数值)Map<String, Double>
(仅允许 Double 值)Map<String, Number>
(允许任何 Number 子类的值)
Map<String, ? extends Number>
指的是可能是上述任何一个的Map (或者,当然,任何其他特定的 Number 子类)。编译器不知道 Map 的值是什么特定类型,但 Map 的值仍然具有特定类型,但该类型不会以任何方式使用?
。
因此,再次查看示例方法:
void doSomething(Map<String, ? extends Number> map) {
// Not allowed. The caller might have passed a Map<String, Double>.
map.put(String, Integer.valueOf(0));
// Not allowed. The caller might have passed a Map<String, Integer>.
map.put(String, Double.valueOf(0));
// Not allowed. The caller might have passed a Map<String, Integer>
// or Map<String, Double>. This method has no way of knowing what the
// actual restriction is.
Number someNumber = generateNewNumber();
map.put(String, someNumber);
}
事实上,您无法向类型为上限通配符的 Map 或 Collection 添加任何内容,因为无法知道这样做是否正确且安全。
对于您的情况,最简单的解决方案是删除通配符:
private void doSomething(Map<String, List<Ps>> map, boolean custom) {
// ...
map.put("stringValue", custom ? new PsList() : new ArrayList<Ps>());
}
如果您确实有具有不同值类型的映射,则需要告诉该方法正在使用的特定类型:
private <L extends List<Ps>> void doSomething(Map<String, L> map,
Supplier<L> listCreator) {
// ...
map.put("stringValue", listCreator.get());
}
然后你可以像这样调用该方法:
if (custom) {
doSomething(psMap, PsList::new);
} else {
doSomething(listMap, ArrayList::new);
}
TA贡献1812条经验 获得超5个赞
你绝对可以做到。这是一个例子:
public class MyClass {
static interface FooList<T> {}
static class Ps {}
static void doSomething(FooList<Ps> list) { }
static class PsList implements FooList<Ps> { }
public static void main(String[] args)
{
FooList psList = new PsList();
doSomething(psList);
System.out.println("HelloWorld!");
}
}
请参阅此处的演示。
添加回答
举报