Learnerslesson
   JAVA   
  SPRING  
  SPRINGBOOT  
 HIBERNATE 
  HADOOP  
   HIVE   
   ALGORITHMS   
   PYTHON   
   GO   
   KOTLIN   
   C#   
   RUBY   
   C++   




Java - Generics

We have seen as opposed to arrays, a List(or Collection) can hold multiple datatypes.

i.e we can insert an Integer or String or Float in the same List.

But this advantage can be a big disadvantage at times.

And thus Generics was introduced. It ensures type safety.

i.e. Just like Arrays it will be holding a single datatype at a time. Just see below:


List <String> arrayList = new ArrayList <String>();

i.e. The above created ArrayList will only be holding Strings. If we try to insert anything other than Strings it would end up with an error.



How Generics deals with Polymorphism ?

List <String> arrayList = new ArrayList <String>();

The above line of code is perfectly fine as, the generic type '<String> ' is in both sides. Now, let us consider the case of Animal and Dog relationship.


java_polymorphism_inheritance


So, in the above case Animal is the parent of Dog. So can we write the below statement:


List <Animal> arrayList = new ArrayList <Dog> ();

Unfortunately the above doesn't work. If you are going to declare 'List <Animal> arrayList' then whatever is assigned to the List must be of generic type <Animal>.

i.e.


List <Animal> arrayList = new ArrayList <Animal> ();

Works fine.


Story :

Let us consider a scenario. There is a God whose responsibility is to manage Animals(Be it a Cat, Dog e.t.c). And he has a behaviour manage().

We are really not concerned about what he manages. We just know his task is to manage only Animal and not Human or Fish.

class ManageAnimal{

  public void manage(List <Animal> animal){
    System.out.println("Manages in his own way");
  }
}

The above method manage() will accept only a List on Animals. That is fine but look at the below problem.


public class TestManager{
  public static void main(String[] args){

  ManageAnimal manageAnimal = new ManageAnimal();
  List <Dog> dogs = new ArrayList <Dog>();
  dogs.add(new Dog());
  dogs.add(new Dog());
  manageAnimal.manage(dogs); // In this step the compiler throws an error.
  }
}

In 'manageAnimal.manage(dogs);' the compiler throws an error. Any guesses why?

If you see above


List <Animal> arrayList = new ArrayList <Dog>();

is not possible.

And even here we are trying to do the same.

i.e. Passing a list of Dog's(eg. List <Dog> dogs)


manageAnimal.manage(dogs);

to 'List <Animal> animal' in


public void manage(List <Animal> animal)

Which is not correct.

So, we change the above code in the below way:


public class TestManager{
  public static void main(String[] args){

  ManageAnimal manageAnimal = new ManageAnimal();
  List <Animal> animal = new ArrayList <Animal>();
  animal.add(new Dog());
  animal.add(new Dog());
  manageAnimal.manage(animal); // This works perfectly fine.
  }
}

So, we simply changed


List <Dog> dogs = new ArrayList <Dog>();

to


List <Animal> animal = new ArrayList <Animal> ();

Then we are adding 'Dog' objects to the Animal reference. Thats perfectly fine.

As you pass 'ArrayList <Dog> ()', compiler will never end up with an error.


Wildcards :

In the above example we have seen, we cannot use the below line of code:


List <Animal> arrayList = new ArrayList <Dog>();

To solve the above problem java provides us with the wildcard (? extends) as shown below.


List <? extends Animal> animals = new ArrayList <Dog>();

The above line is selfexplanatory. It says we can add any subclass of Animal to the List.

So, let's modify the above example with the wildcard used.


class ManageAnimal{

  public void manage(List <? extends Animal> animals){
    //animals.add(new Dog()); // This line is not allowed.
    System.out.println("Manages in his own way");
  }
}

public class TestManager{
  public static void main(String[] args){

  ManageAnimal manageAnimal = new ManageAnimal();
  List <Dog> dogs = new ArrayList <Dog>();
  dogs.add(new Dog());
  dogs.add(new Dog());
  manageAnimal.manage(dogs); // There is no problem in this step.
  }
}