First of all, your question is quite legitimate, although with your examples, it's hard to explain / understand the differences.
In all the variants, you want to define a method empTest()
that accepts an ArrayList of Employees or subclasses of Employee. You do this with
public void empTest(ArrayList<? extends Employee> list) { ... }
So, what are the other syntax variants meant for? Let's use a different example, as your empTest()
method doesn't need anything else.
Say, we want to add an employee to a list using something like addEmp(list, emp);
. First idea might be:
public void addEmp(ArrayList<Employee> list, Employee emp) { ... }
But that won't do the job, as you won't be able to pass an ArrayList<ContractEmployee>
into the method. Next attempt:
public void addEmp(ArrayList<? extends Employee> list, Employee emp) { ... }
Now it accepts the list, but it also allows you to pass an ArrayList<ContractEmployee>
in combination with a PermanentEmployee
, and adding a PermanentEmployee
to an ArrayList<ContractEmployee>
isn't allowed. The compiler will flag the line in the method body where you add the employee, as illegal.
So, what we need here, is to check for using the same type of employee in both places, and that's what the named type parameters can be used for.
public <T extends Employee> void addEmp(ArrayList<T> list, T emp) { ... }
This says: it's ok to pass in an ArrayList
of any subtype of Employee
, and we call that subtype T
. Then the emp
argument must also come from the same subtype T
(or from a sub-subtype because of normal class inheritance).
If being an Employee
or not doesn't make a difference to the method, you can even write
public <T> void addEmp(ArrayList<T> list, T emp) { ... }
To summarize it:
- Use the
<... extends SomeClass>
constructs if need more variability than the plain <SomeClass>
construct.
- If it's just one place where you need that variability, there's often no need to introduce a name for the subclass, so
<? extends SomeClass>
in the method's parameter list does the job.
- If you need the same subclass in multiple places, you need to give it a name, so use something like
<T extends SomeClass>
in front of the return-type declaration and use T
without the angle brackets in the parameters list.
Regarding syntax:
- If you need to introduce a name for the type parameter, this is done before the return type.
- In the method return type or the method parameter list, you can only use names that already exist, or use unnamed wildcard constructs.