-1

I have got some error trying to use basic generics. Below is a simplified version of the challenge;

public final class Example {
    private List<? extends Liquid> holder;
    private List<List<? extends Liquid>> holder2;

    public Example() {
        holder = new ArrayList<>();
        holder2 = new ArrayList<>();
    }

    public <T extends Liquid> void add(int position, T value) {
        if (holder != null)
            holder.add(position, value); //<- Error Here
    }

    public <T extends Liquid> void add(int position, List<T> value) {
        if (holder != null)
            holder.add(position, value); //<- This works
    }
}

Client

I want the variable holder to store different subtypes of Liquid. Example;

exampleInstance.add(0, new Water()); 
exampleInstance.add(1, new Juice());
Orson
  • 14,981
  • 11
  • 56
  • 70
  • 1
    The key insight here is that `List extends Liquid>` does **not** mean "a list of various subclasses of `Liquid`". It means "a list of various objects, that are all of the *same* subtype of `Liquid`, but I don't know which one specifically". If you understand that, the rest of the behavior here should make sense. – Daniel Pryden Mar 10 '18 at 13:01

1 Answers1

2

Declaring your field with a upperbound wildcard : List<? extends Liquid> holder makes sense only if you would assign to a subclass of it or if you want to pass it in a method.
In this case, you cannot add anything but null in the List.

You are not in its use case. So instead of, declare private List<Liquid> holder to be able to add Liquid instances in your List.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • I want the variable holder to have different subtypes of Liquid. Example; exampleInstance.add(0, new Water()); exampleInstance.add(0, new Juice()); – Orson Mar 10 '18 at 13:01
  • 2
    And it will as you can add in a `List` any `Liquid` instances (so Liquid or subclass of) – davidxxx Mar 10 '18 at 13:03
  • I am trying it out just a sec. – Orson Mar 10 '18 at 13:12
  • What is confusing is that in the same class, have another local variable like `private List> holder2;` and it works this way with the wildcards. With the other local variable (without your solution) `private List extends Liquid> holderForSingle;` does not work. Why is it behaving differently? +1 for your solution. – Orson Mar 10 '18 at 13:17
  • Because the upperbound wildcard is not specified at the same level. So you don't have the same restriction. You cannot add no null elements in a `List extends Foo>` but you can in `List>` – davidxxx Mar 10 '18 at 13:20
  • Ok, i get it now. – Orson Mar 10 '18 at 13:22