Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lower bounded wildcard

I have been trying to understand the concept and rationale behind the lower bounded wildcard in Java Generics. I can understand the reasoning behind the upper bounded wildcard being read only and where and how it can be used. I am still not able to get a grasp of the lower bounded wildcard. I have a set of classes which follow the below hierarchy. (Automobile is the base class.)

Automobile
    - Bus
        - Minibus
        - Doubledecker
        - Electricbus
    - Car
        - Sedan
        - Hatchback
        - Coupe
    - Truck
        - Minivan
        - Pickuptruck
        - Suv
            - Fullsuv
            - Midsuv

Now I am trying to build a (flexible) list and add objects of different types to it.

import java.util.ArrayList;
import java.util.List;

public class Garage {

    public static void main(String[] args)
    {
        List<? super Suv> list = null;

        Suv s = new Suv();
        Truck t = new Truck();
        Automobile a = new Automobile();

        list = new ArrayList<Suv>();
        list.add(s); // declared as List<? super Suv> but actually List<Suv>. No compilation error

        list = new ArrayList<Truck>();
        list.add(t); // declared as List<? super Suv> but actually List<Truck>. Compilation error

        list = new ArrayList<Automobile>();
        list.add(a); // declared as List<? super Suv> but actually List<Automobile>. Compilation error
    }
}

I am able to add an instance of Suv to List<? super Suv>. But I get compilation error when I try to add instances of Truck or Automobile to the same list. Isn't the List<? super Suv> flexible enough to take any instances of Suv or its super classes? Truck and Automobile are higher up in the hierarchy tree. Why am I not able to add instances of these to the list?

like image 489
Andulos Avatar asked Oct 19 '22 21:10

Andulos


1 Answers

List<? super Suv> should be read as "A list whose element type is a super type of Suv".

Now, let's look at these two lines:

list = new ArrayList<Automobile>();
list.add(a); // where a is an Automobile

The first line is ok, since ArrayList<Automobile> is indeed "a list whose element type is a super type of Suv".

But let's read out the second line: Add some Automobile to a list whose element type is as super type of Suv.

As far as the compiler knows from the static types,

  • list could refer to a List<Truck> (since Truck is a super type of Suv) and
  • t may refer to a Car (since a Car is an Automobile)

So the compiler complains to make sure you're not adding a Car to a list of Trucks.


Useful reading:

  • Java Generics: extends, super and wildcards explained (section When to use extends and super)
like image 63
aioobe Avatar answered Oct 22 '22 14:10

aioobe