2012-03-23 88 views
0

在:泛型与延伸

public class Organic<E> { 
    void react(E e) { 
    } 

    static void main(String[] args) { 
     Organic<? extends Elem> compound = new Organic<Elem>(); 
     compound.react(new Elem()); 
    } 
} 

class Elem {} 

为什么我得到下面的编译错误?

方法react(capture#1-of ? extends Elem)在类型Organic<capture#1-of ? extends Elem>不适用于参数(Elem

+0

为什么你使用不同的参数为变量声明和对象实例?你想达到什么目的? – biziclop 2012-03-23 11:35:59

+0

我不想实现任何目标。这只是一本书的练习。 – 2012-03-26 07:45:45

回答

1

http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

List是有界的通配符的示例。这个?代表着未知类型,就像我们之前看到的通配符一样。然而,在这种情况下,我们知道这个未知类型实际上是Shape的一个子类型。 (注意:它可以是Shape本身,也可以是一些子类;它不需要从字面上扩展Shape。)我们说Shape是通配符的上界。

像往常一样,使用通配符的灵活性需要付出代价。这个价格是现在写入方法体内的形状是非法的。例如,这是不允许的:

public void addRectangle(List<? extends Shape> shapes) { 
    // Compile-time error! 
    shapes.add(0, new Rectangle()); 
} 

你应该能够找出为什么上面的代码是不允许的。 shapes.add()的第二个参数的类型是?扩展Shape - Shape的未知子类型。由于我们不知道它是什么类型,我们不知道它是否是Rectangle的超类型;它可能或可能不是这样一个超类型,所以在那里传递一个Rectangle是不安全的。

具体谈论你的解决方案,你不能说与Elem类型的对象作出反应,与类型Organic<? extends Elem>你可以合法地分配compound = new Organic<ElemSubClass>() - 然后反应会导致编译错误,你不能把它传递一个超类对象。

0

修改你的方法reactas每下面,它的工作:

void react(Elem e) { 

} 
0

的“?当你想允许用户只传递SomeClass或它的子类作为一个通用参数时,扩展SomeClass'用于定义泛型类型。这意味着你可以这样做:

public class Organic<E extends Elem> { 
    void react(E e) { 
} 

,如果你想有机与ELEM的子类的参数进行调整。在主要的方法,你可以做这样的事情:

Organic<Elem> compound = new Organic<ElemOrAnyElemSubclass>(); 

,因为我知道没有必要在方法体中使用

Organic<? extends Elem> 

整个代码:

public class Organic<E extends Elem> { 
void react(E e) { 
} 

static void main(String[] args) { 
    Organic<Elem> compound = new Organic<Elem>(); 
    compound.react(new Elem()); 
    } 
} 
class Elem {} 
class ElemSubClass extends Elem {} // if you need 

而且你在表达的左侧和右侧部分使用相同的通用类型。这是非法的: Organic compound = new Organic();

不知道它是你想要的,但希望它会帮助