我有Map<K, V>
并希望将其投放到Map<K, U>
V
扩展U
。示例:我想从Map<String, String>
转到Map<String, Object>
。所有类型的集合都存在此问题。
This question已经有一个“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);
关于这个例子的一些问题:
List<String>
转换为List<Object>
时可能会出现什么问题,因为所有字符串都是对象?我的具体问题:
我有一个Map<Integer, Map<Vector2i, MyClass> > map = ...
,其中包含每个级别的地图。级别0上的地图是Map<Vector2i, MySubClass> special = ...
类型。我现在希望special
成为密钥0的map
的一部分,以便可以将对密钥0的map
的访问视为普通的Map<Vector2i, MyClass>
对象。
情况是只读的,这意味着写入map
和special
会分开发生。
答案 0 :(得分:1)
投射List&lt; String&gt;时可能出错的地方到列表&lt;对象&gt;既然所有的字符串都是对象吗?
从这个角度来看:如果它是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());
}
一旦ClassCastException
与s
不符合预期,您就会点击String
。
<强> [附录] 强>
为什么这(1)不能编译?是一种让它编译而不是hack(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);
}
现在,该方法接受任何类型List
的{{1}}个。但是您无法在方法内的列表中添加任何内容(在Number
旁边),因为实际类型在运行时是未知的。
这个解释可能有点随意。如果您想更详细地了解,请搜索&#34; PECS规则&#34; (&#34;生产者扩展,消费者超级&#34;)。同样适用于任何泛型类型,例如null
,当然。