将 Map 强制转换为具有超类泛型类型的映射



我有一个Map<K, V>,想把它投射到V扩展UMap<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>对象。

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

将 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);
}

现在该方法接受任何类型的NumberList。但是您不能在方法内部向列表中(null旁边(添加任何内容,因为在运行时不知道实际类型。

这个解释可能有点随意。如果您想了解更多细节,请搜索"PECS 规则"("生产者扩展,消费者超级"(。这同样适用于任何泛型类型,例如Map当然。

相关内容

  • 没有找到相关文章

最新更新