【发布时间】:2021-09-12 10:52:50
【问题描述】:
我班上有一个protected Map<String, List<Animal>> animals;。在我的构造函数中,我有
animals.put("dogs", new ArrayList<Animal>());
animals.put("cats", new ArrayList<Animal>());
一切正常,正如预期的那样。如果我想要Dog 或Cat,我只需要从地图中获取并投射即可。
但是,如果我想要呢
animals.put("dogs", new ArrayList<Dog>());
Java 不允许我这样做。我也在this SO answers 中读到了它,但我需要它,因为我使用的是 JSF,并且我需要在页面的 EL 表达式中使用 Animal 没有的 Dog 方法。
自从我为Animal 创建了一个工厂后,我想使用工厂来获取正确的对象类型,但我觉得有点奇怪。
有什么方法可以使用animals.put("dogs", new ArrayList<Dog>()); 或其他替代方法吗?
PS:我使用的是 Java 7
【问题讨论】:
-
好吧,您可以使用
Map<String, List<? extends Animal>> animals;,这将允许您执行animals.put("dogs", new ArrayList<Dog>());,但您仍然无法在不强制转换的情况下从该地图中获得ArrayList<Dog>。毕竟,映射可以包含其他键的其他类型,那么编译器怎么知道要在这里返回什么类型呢?您需要提供该演员表,可能使用List<Dog> getDogs() { return (List)animals.get("dogs"); }之类的特定方法(原始演员表是必要的,因此编译器不会抱怨。 -
地图的泛型支持所有相同类型的值,并且您有一个地图,其中值的类型略有不同。听起来您应该使用
Map<String, List<? extends Animal>>,但如果您想以List<Dog>而不是List<? extends Animal>检索您的狗列表,您将不得不强制转换它。你无法避免在某个地方投射。 -
如果你有这个问题,你可能设计的继承层次结构不正确。