无法投射通用套装?

时间:2011-06-11 23:35:27

标签: java generics

我今天遇到了一个有趣的问题。请考虑以下代码

public static class Parent {}
public static class Child extends Parent {}

Set<Child> childs = new HashSet();
Set<Parent> parents = (Set<Parent>)childs; //Error: inconvertible types

Parent parent = (Parent)new Child(); //works?!

为什么这样的演员不会有效?我希望由于泛型的各种规则,隐式转换不起作用,但为什么不能进行显式转换呢?

4 个答案:

答案 0 :(得分:16)

演员表不起作用,因为Java generics are not covariant

如果编译器允许这样做:

List<Child> children = new ArrayList();
List<Parent> parents = (List<Parent>)children;
那么在这种情况下会发生什么?

parents.add(new Parent());
Child c = children.get(0);

最后一行会尝试将Parent分配给Child - 但Parent 不是Child

所有Child都是Parent(自Child extends Parent起),但所有Parent都不是Child

答案 1 :(得分:1)

Set<Parent>可以包含Parent的任何子类。 Set<Child>可以包含Child的任何子类。因此,Parent的子类不是Child的子类,而是允许其中一个而不是另一个子类,使它们成为不兼容的类型。

答案 2 :(得分:1)

因为一组孩子(原文如此)不是一组父母。定义泛型(参数化)集实际上与定义新类相同,因此您定义了两个不相交的类。

答案 3 :(得分:1)

尽管如此,超类型的泛型有点不同:

Set<Child> childs = new HashSet();
Set<? extends Parent> parents = childs;

Set是超类型的Set和Set

我建议您阅读this docs about generics以了解通用容器之间没有继承,因为它不是继承。毕竟,继承意味着专业化。想象一个用于容纳动物的盒子,好吧它可以通过一个只包含老虎的盒子来获得但是它意味着盒子可以为老虎做的,当然,也可以做超级类型可以做的所有事情,包括做好事所有动物的盒子。对于人类来说,考虑两种类型的分类法都有一些非常混乱的东西:超级层次结构(专门化,继承)和meronymic层次结构(容器/包含)。

在你的最后一行中,不需要同时投射:

Parent parent = new Child(); 

斯特凡