gpt4 book ai didi

java - 通用列表的映射不能很好地转换

转载 作者:行者123 更新时间:2023-11-29 08:04:44 25 4
gpt4 key购买 nike

与其尝试用文字表达,不如举个例子:

我有一个 Animal 类,以及扩展 Animal 的 Dog、Fish、Cat 等。

我有三种不同的方法,它们返回 Map<String,List<Dog>>, Map<String,List<Fish>>, Map<String,List<Cat>> .我们将调用这些 getDogMap、getCatMap 和 getFishMap。

我正在编写一个通用方法,它根据各种参数调用这些方法之一。这是我希望被允许做的事情:

public void <A extends Animal> doSomething(){

Map<String,List<A>> someMap;

if(someCondition){
someMap = getDogMap();
}else if(anotherCondition){
someMap = getFishMap();
}else{
someMap = getCatMap():
}
}

或者至少,通过类型转换 ala someMap = (Map<String,List<Dog>>) getDogMap();

但是,这不起作用。 Eclipse 告诉我 "Type mismatch: cannot convert from Map<String,List<Dog>> to Map<String,List<A>>"如果我尝试强制转换,它会告诉我 "Cannot cast from Map<STring,List<Dog>> to Map<String,List<A>>" .

我做错了什么?

最佳答案

public void <A extends Animal>并不意味着“A 是扩展Animal 的任何类型”,它意味着“A 是扩展Animal 的特定类型之一”。您需要使用以下声明:

public void doSomething() {
Map<String, ? extends List<? extends Animal>> someMap;
// ...
}

构造 ? extends Animal是你表达“任何扩展 Animal 的类型”的方式。

您必须使用该声明的原因是,与直觉相反,泛型类型之间的子类型关系的工作方式与它们在常规类型之间的工作方式并不完全一致。例如,List<Dog>Collection<Dog> 的子类型.它不是 List<Animal> 的子类型, 或 Collection<Animal>等等。不允许这样做的原因称为堆污染,在Angelika Langer's FAQ 中也有解释。 . List<Dog>然而,是 List<? extends Animal> 的子类型. List<? extends Animal> 类型的变量可能分配了一个 List<Dog> , 或 List<Cat> , 或 List<Animal> .重要的是编译器不知道它是哪一个,只是知道它是其中之一。

就像List<Dog> 不是 List<Animal> 的子类型,类似地认为 Map<String, List<Dog>> 不是 Map<String, List<? extends Animal>> 的子类型.

证明泛型为何如此工作的最好方法是反证法;也就是说,显示会导致错误的(损坏的)代码示例是“直观地”工作的泛型。所以,如果 List<Dog>List<Animal> 的子类型,以下代码将是有效的:

List<Dog> dogs = new ArrayList<Dog>();
List<Animal> animals = dogs; // unsafe cast

// this operation violates type safety
animals.add(new Cat());

// would assign a Cat to a variable of type Dog without a compile error!
Dog dog = animals.get(0);

同样,对于您的 Map :

Map<String, List<Dog>> dogses = new HashMap<String, List<Dog>>();
Map<String, List<? extends Animal>> animalses = dogses; // unsafe cast

List<Cat> cats = new ArrayList();
cats.put(new Cat());
animalses.put("cats", cats);

List<Dog> dogs = dogses.get("cats");
Dog dog = dogs.get(0); // uh-oh

关于java - 通用列表的映射不能很好地转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12014696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com