user2833621
user2833621

Reputation: 165

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

Upvotes: 2

Views: 1404

Answers (2)

Vlasec
Vlasec

Reputation: 5546

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>, 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.

Upvotes: 0

Eran
Eran

Reputation: 393851

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)

Upvotes: 6

Related Questions