0

I am working on upper bound wild card( ? ) in arraylist. it is not working when i declare an arraylist using wildcard. For Example : i have three classes:

1) Person class:

 public class Person {  
}

2) employee class which extends person:

public class Employee extends Person {

}

3) dept class which extends employee.

public class Dept extends Employee{

}

now i want the objects of these three classes should be add to arraylist in a seperate class as below.

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

     Person p1 =new  Person();
     Employee e1 = new Employee();
     Dept d1 = new Dept();
     ArrayList<? extends Person> al =new ArrayList<Person>();

     al.add(p1);
     al.add(e1);
     al.add(d1);


 }
}

The last three lines in the code showing me the following error: The method add(capture#1-of ? extends Person) in the type ArrayList is not applicable for the arguments (object type).

But from arraylist of type "? extends person", can take "any object extends person" , but why its not accepting employee object which extends person.

ngrashia
  • 9,869
  • 5
  • 43
  • 58
Naz
  • 390
  • 1
  • 4
  • 15

2 Answers2

1

An ArrayList<? extends Person> could be a ArrayList<Employee>. In that case, you would not be allowed to add a non-Employee. Since the compiler does not know the type, it does not allow you to add anything.

Note that the compiler does know that all elements that are already in the list will be subclasses of Person. So get works even when add does not:

  Person x = al.get(0);

If you want to have a List that can take either of your three types, use ArrayList<Person>.

Thilo
  • 257,207
  • 101
  • 511
  • 656
1

The java generics are implemented with concept of Erasure that means any specific type information is erased when you use generics. Inside generics, you are actually working with Object for example List (List < String >) and List (List < Integer >) are of same type at runtime. The generic types are present only during static type checking, after which every generic type in the program is erased by replacing it with a non-generic upper bound.

As erasure removes the type information only methods you can call for unbounded generic parameter are that of Object, but if you can constrain that parameter to be a subset of types, then you can call methods in that subset. To perform this constrain java generics uses extends keyword.

Given this background, when you specify ArrayList (ArrayList < ? extends Person >), you actually mean "a list of any type that is inherited from Person". This does not mean that list will contain any type of person. The wildcard (?) refers to definite type, so it means some specific type (of type Person) which this list does not specify will be in list. So the list can contain specific type of person but you don't know which one is that. And hence you can not add objects of type Person to this list.

But, when you say ArrayList (? super Person) you say that this list contains specific objects derived from Person that is, objects whose base or super type is Person. Hence it is safe to pass a Person or anything derived from Person into this list. And hence it works.

Hope it help!

Amit K
  • 51
  • 5