2011-06-11 66 views
3

今天我遇到了一个有趣的问题。考虑下面的代码无法投射通用集?

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?! 

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

+0

'可能是。 – 2011-06-11 23:46:18

+0

@ahmet说'HashSet '_where?_ – 2011-06-12 00:01:12

回答

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

最后一行将尝试给ParentChild —但Parent不是Child

所有ChildParent(因为Child extends Parent),但所有ParentChild

+0

这是一个有趣的观点。尽管这对我的API造成了严重破坏。谢谢你的回答 – TheLQ 2011-06-12 00:01:49

+0

没问题。如果它很糟糕,而且你不明白正确的参数化API的方法,请用一些具体的例子来问另一个问题,我会看看。 – 2011-06-12 00:06:28

1

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

1

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

1

虽然,超类型的仿制药的工作有一点不同:

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

是集超类型设置,并设置

我建议你阅读this docs about generics要明白,有是通用之间没有继承容器只是因为它不是继承。毕竟,继承意味着专业化。想想一个专门用来装动物的盒子,好吧,它可以由一个只包含老虎的盒子产生,但这意味着盒子可以为老虎做,当然,也可以做所有超级类型可以做的事情,包括做一个好东西所有动物的盒子。对于人类来说,想到这两种类型的分类学都是非常混乱的:高层次的层次结构(专业化,继承)和层次结构层次结构(容器/包含)。

在你的最后一行,无需投既不:如果你说'HashSet的

Parent parent = new Child(); 

斯特凡