简体   繁体   中英

Generics with extends

In:

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 {}

Why do I get the following compilation error?

The method react(capture#1-of ? extends Elem) in the type Organic<capture#1-of ? extends Elem> Organic<capture#1-of ? extends Elem> is not applicable for the arguments ( Elem )

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

List is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.

There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into shapes in the body of the method. For instance, this is not allowed:

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

You should be able to figure out why the code above is disallowed. The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there.

Specifically talking about your solution, you cannot call react with an object of Elem type, as with type Organic<? extends Elem> Organic<? extends Elem> you can legally assign compound = new Organic<ElemSubClass>() - and then react will cause compile error as you cannot call it passing a super class object.

modified your method reactas per below, it will work:

void react(Elem e) {

}

The '? extends SomeClass' is used in defining generic types when you want to allow user to pass only SomeClass or it's subclasses as a generic parameter. It means you can do this:

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

if you want Organic to be parametrized with subclasses of Elem. In main method you can do something like this:

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

as i know there's no need to use

Organic<? extends Elem>

in method body.

Entire code:

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

Moreover you have to use the same generic types in both left and right part of expression. This is illehal: Organic compound = new Organic();

Not sure it is what you wanted but hope it will help

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM