我有一个Map<K, V>
,想把它投射到V
扩展U
的Map<K, U>
。示例:我想从Map<String, String>
转到Map<String, Object>
。所有类型的集合都存在此问题。
这个问题已经有一个"hacky"解决方案的答案,并且解释了为什么强制转换泛型类型通常是一个坏主意。但是,让我们从 Voo 的答案中重新审视
一下示例:List<String> m = Something;
m.add("Looks good.");
m.add("42");
List<Object> s = (List<Object>)m; // (1) does not compile
List<Object> t = (List)m; // (2) compiles with warnings
Object myObject = s.get(1);
关于此示例的几个问题:
- 为什么这个(1(不编译?除了黑客(2(之外,还有一种方法可以使其编译吗?
- 将
List<String>
转换为List<Object>
时可能出现什么问题,因为所有字符串都是对象?
我的具体问题:
我有一Map<Integer, Map<Vector2i, MyClass> > map = ...
,其中包含每个级别的地图。级别 0 上的地图类型为Map<Vector2i, MySubClass> special = ...
。我现在希望special
成为键 0map
的一部分,以便可以将对键 0 的map
的访问视为正常的Map<Vector2i, MyClass>
对象。
这种情况是只读的,这意味着写入map
和special
是分开发生的。
将 List
强制转换为 List
从这个角度来看:如果它是一个List<Object>
,一切都可以添加到其中。因此,这可能会出错,例如:
List<Object> t = (List)m; // (2) compiles with warnings
t.add(1235); // it's a List<Object>, so we can add an Integer
for (String s : m) { // m only contains Strings, right?!
System.out.println(s.length());
}
一旦s
不是预期的String
,您就会遇到ClassCastException
。
[增编]
为什么这个(1(不编译?除了黑客(2(之外,还有一种方法可以使其编译吗?
我不确定,你的实际问题是什么,所以我只是猜测。但是我第一次遇到类似的问题,是这样的:
/* Just example; functionality does not matter, just that it accepts List<Number> */
public static void printNumbers(List<Number> numbers) {
numbers.forEach(System.out::println);
}
上面的实用程序方法采用List<Number>
,只打印它们中的每一个。现在,您的代码中通常有List<Integer>
、List<Double>
等。但是下面的代码会节点编译:
List<Integer> integers = Arrays.asList(1, 2, 3);
printNumbers(integers);
现在,与其进行野生转换(当然,如果您可以控制虚构的效用方法(,不如执行以下操作:
public static void printNumbers(List<? extends Number> numbers) {
numbers.forEach(System.out::println);
}
现在该方法接受任何类型的Number
List
。但是您不能在方法内部向列表中(null
旁边(添加任何内容,因为在运行时不知道实际类型。
这个解释可能有点随意。如果您想了解更多细节,请搜索"PECS 规则"("生产者扩展,消费者超级"(。这同样适用于任何泛型类型,例如Map
当然。