泛型与扩展

时间:2012-03-23 11:32:24

标签: java generics

在:

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

3 个答案:

答案 0 :(得分: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的超类型;它可能是也可能不是这样的超类型,所以在那里传递一个矩形是不安全的。

特别是在谈论您的解决方案时,您无法调用Elem类型的对象作出反应,因为类型Organic<? extends Elem>您可以合法地分配compound = new Organic<ElemSubClass>() - 然后反应将导致编译错误,你不能称它传递超类对象。

答案 1 :(得分:0)

根据以下修改了方法反应,它将起作用:

void react(Elem e) {

}

答案 2 :(得分:0)

'?当你想允许用户只传递SomeClass或它的子类作为泛型参数时,使用extends SomeClass'来定义泛型类型。这意味着你可以这样做:

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

如果您希望使用Elem的子类对Organic进行参数化。在main方法中,您可以执行以下操作:

    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

此外,您必须在表达式的左右两部分使用相同的泛型类型。这是非法的:         有机化合物=新有机();

不确定这是你想要的,但希望它会有所帮助