6

最近,当我遇到无法解释的泛型转换问题时,我正在重构一个泛型方法。最后我意识到我可以完全不用 T 类型(只是自己内联它),但我仍然对转换失败的原因感到好奇。我创建了这个最小的例子来说明这个问题。

有人可以解释为什么转换失败并且解决方法有效吗?

public <K, T extends List<K>> void castLists(List<T> list, K kForBinging) {
    Map<Integer, List<T>> map = mapSizeToList(list);
    // Type mismatch: cannot convert from Map<Integer,List<T>> to Map<Integer,List<List<K>>>
    // Map<Integer, List<List<K>>> expandedMap = map;

    // Added after accepting answer, legal assignment:
    Map<Integer, ? extends List<? extends List<K>>> expandedMap = map;

    // Originally proposed 'work around'
    Map<Integer, ?> lessSpecific = map;
    @SuppressWarnings("unchecked")
    Map<Integer, List<List<K>>> canCast = (Map<Integer, List<List<K>>>)lessSpecific;
    // ...
}

public <A> Map<Integer, List<A>> mapSizeToList(List<A> list) {
    Map<Integer, List<A>> map = Maps.newHashMap();
    // ...
    return map;
}
4

1 回答 1

6

我相信你需要协方差与泛型才能做这些事情。这似乎不受 Java 支持

即在 Java 中,如果T是 的子类型List<K>并不意味着List<T>是 的子类型List<List<K>>或是Map<Integer,List<T>>的子类型Map<Integer, List<List<K>>>。这就是赋值错误的原因。

Covariance would allow you to do this because with it, if template parameters have a subclass-superclass relationship, the defined classes will also have the exact same relationship. This would make this assignment possible. Scala (among other (functional programming?) languages) supports covariance and its complement contravariance.

于 2012-12-20T10:02:54.493 回答