简体   繁体   中英

Collection<? extends T> means?

Why is it throwing compilation error at line 23. 'a' is an object of class Apple and col is a list containing Apple objects, but still, it is throwing a compilation error mentioned below:

The method add(capture#1-of ? extends Fruit) in the type Collection is not applicable for the arguments (Fruit)

public class Basket {
    List<Fruit> list;
    public Basket() {
        list = new ArrayList<>();
    }
    public Basket(List<Fruit> plist) {
        list = plist;
    }

   void addFruit(Collection<? extends Fruit> col) { // this does not work
// void addFruit(Collection<Fruit> col) { // this works
        Fruit a = new Apple();
        Apple a1 = new Apple();
        Fruit f1 = new Fruit();
        col.add(a);// line 23
    }

    int getSize() {
        return list.size();
    }

    public static void main(String[] args) {
        Fruit f1 = new Apple();
        Fruit f2 = new Apple();
        Fruit f3 = new Apple();
        List<Fruit> list = new ArrayList<>();
        list.add(f1);
        list.add(f2);
        list.add(f3);
        Basket b = new Basket(list);
        b.addFruit(list);
        System.out.println(b.getSize());
    }
}

class Fruit {
}

class Apple extends Fruit {
}

Collection<? extends Fruit> col Collection<? extends Fruit> col means that col is a Collection of Fruit or a Collection of some sub-class of Fruit , such as Collection<Apple> or Collection<Banana> .

You can't add an Apple to a Collection that might be a Collection<Banana> .

If you want to be able to add any Fruit , change the signature to:

void addFruit(Collection<Fruit> col)

A collection can only contain entries of some type and its subtypes. For example if you have a Collection<Banana> , it can only contain bananas.

Even though Banana is a sub-class of Fruit , Collection<Banana> is not type-compatible with Collection<Fruit> . It might seem a bit counter-intuitive, but think of it this way: In a Collection<Banana> you only expect a Banana . You don't expect an Apple . But if you have a Collection<Fruit> , you can have all sorts of fruit in it. And you can add any fruit to the collection.

If you cast your Collection<Banana> to Collection<Fruit> , you can add apples in it. Then you try to pull a banana out of your Collection<Banana> and you get an apple. Since you cannot cast Apple to Banana , a ClassCastException is thrown at runtime and your code fails.

So, in your case, you probably want a Collection<Fruit> as suggested by @Eran. However, to answer your question in detail: If you had a Collection<Banana> , you could use the collection as Collection<? extends Fruit> Collection<? extends Fruit> , but you are limited to methods that don't have generic input param.

For example you can mutate the collection using retainAll , remove and a few others, you can as well as use all read-only operations, but you can't add new apples to your collection of bananas.

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