2017-07-31 25 views
0

我有一个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); 

这个例子几个问题:

  • 为什么会出现这种(1)无法编译?除了黑客(2)之外,是否可以编译它?
  • List<String>投射到List<Object>时可能会出错,因为所有字符串都是对象?

我的具体问题:

我有一个Map<Integer, Map<Vector2i, MyClass> > map = ...包含地图为每个级别。 0级地图的类型为Map<Vector2i, MySubClass> special = ...。我现在想要special为关键字0的map的一部分,因此可以将对关键字0的map的访问视为正常的Map<Vector2i, MyClass>对象。

情况是只读的,这意味着写入mapspecial分开发生。

+0

也许这个答案有帮助:https://stackoverflow.com/questions/4288084/how-to-convert-liststring-to-listobject –

+0

我很好奇*为什么*你认为你需要这个演员。这可能是一个XY问题。 – shmosel

回答

1

铸造名单<字符串>到列表<对象>因为所有的字符串是对象的时候怎么可能出问题?

从这个角度来看它:如果它是一个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)不编译?除了黑客(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 s的List s。但是你不能在该方法内的列表中添加任何内容(null),因为实际类型在运行时是未知的。

这个解释可能有点不经意。如果您想更详细地了解,请搜索“PECS规则”(“生产者延伸,消费者超级”)。当然,同样适用于任何通用类型,例如Map

+0

我明白了。我专注于'阅读'部分,完全忘了写作时仍然有可能搞砸了。 – piegames

+0

另一个要添加的是'类型删除'的概念,即泛型是一个编译时间概念。可以在运行时通过执行'List s =(List )List.class.cast(m);',但它是一个潘多拉盒子。对于一些额外的见解,请参阅:https://stackoverflow.com/questions/14524751/cast-object-to-generic-type-for-returning –

+0

'?扩展'解决方案解决了我的问题,谢谢。 – piegames