2010-09-10 54 views
3

我想这个代码的一些变种在Java编译。因为名单<Ÿ>和列表<X>不兼容压倒一切的名单结果类型在Java中

class X 
{ 
    List<X> getvalue(){...}; 
} 

class Y extends X 
{ 
    List<Y> getvalue(){...}; 
} 

javac的(1.6)返回一个错误。

的一点是,我想编译器 承认,列表<Ÿ>是兼容的返回类型 列出<X>如果Y是X 我想这个原因的亚型是简化使用用户定义的工厂类。

注:这个问题有点像 this question 但为Java。

+1

请格式化代码以使其可读。 – Carlos 2010-09-10 19:50:08

+0

读http://stackoverflow.com/questions/2754756/how-to-cast-a-list-of-inheriting-objects-to-a-collection-of-objects-in-java/2755050也许HTTP:/ /stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures/2777297 – 2010-09-10 19:52:41

+0

修正了他:)只是带了我四次尝试......大声笑。 – Skurmedel 2010-09-10 19:54:04

回答

6

不,这不是一个兼容的类型。您不能转换从List<Y>List<X>只是因为YX一个子类。试想一下:

List<Banana> bananas = new ArrayList<Banana>(); 
List<Fruit> fruit = bananas; 
fruit.add(new Apple()); 
Banana banana = fruit.get(0); // But it's an apple! 

您可以使用有界通配符在Java中表达有限的差异,给一些东西,有效:从试图

List<? extends Fruit> fruit = bananas; 

,因为这会阻止你(在编译时)添加额外的结果 - 编译器知道它可能是无效的。

我会建议安格朗格Java Generics FAQ进一步阅读这样的事情。

+0

建议任何需要了解Java泛型如何工作的人使用http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf。 – Carlos 2010-09-10 19:53:16

+0

谢谢,这是一个很好的指针。 – 2010-09-10 19:55:34

+0

句子“您可以在Java中使用差异...”似乎不正确(如果考虑方差的定义)。也许你应该说“你可以在Java中使用有界通配符”。您还可以添加有界通配符,使您可以指定use-site上的类型参数的协方差/对比度约束。 – 2010-09-14 10:34:55

7

在Java中,重写的方法的返回类型必须与该方法的被重写来协变。

java.util.List类不是协变的(事实上,没有Java类,这是因为缺乏声明站点差异注释)。换句话说,B <: A并不意味着List<B> <: List<A>(作为子类型的<:)。因此你的代码不会检查。


在Java中,您有定义站点差异。因此,以下类型:

import java.util.List; 

class X { 
    List<? extends X> getvalue() { return null; } 
} 

class Y extends X { 
    List<Y> getvalue() { return null; } 
}