Reputation: 1586
In Java I have an interface I
, a class C
and a class D
, both implementing I
:
interface I
{
//some method signatures
}
class C implements I
{
//implement methods from I
}
class D implements I
{
//implement methods from I
}
Now I create a List holding elements of class C
, and a second List holding elements of D
:
List<C> c = new LinkedList<C>();
List<D> d = new LinkedList<D>();
I have a method that I want to apply to all Lists that hold elements implementing interface I
:
public void modifyList(List<I> l)
{
//call some method defined in I
}
However, when I try to call that function the compiler throws an error:
public void testModification()
{
modifyList(c);
modifyList(d);
}
==> The method modifyList(List<I>) in the type [...] is not applicable for the arguments (List<C>) / (List<D>)
I can get it to work by redefining my List, such that it reads
List<I> c1 = new LinkedList<I>();
But now c1
can hold Elements from both classes C and D, which is something I want to avoid. How can I create a List such that I can define exactly what class' elements it should hold but still use it as a parameter for my function?
Upvotes: 4
Views: 2531
Reputation: 7032
As you found out, you can't pass List< C > as a parameter to a method expecting List< I >. This is because that method could (legally) add a D to the List< I >, which would violate the generic type invariant of the List< C > .
Changing the method signature to:
public void modifyList(List<? extends I> l)
{
//call some method defined in I
}
Has the behavior you want: takes list of any generic type that implements I as an argument.
Upvotes: 4
Reputation:
You can try using
public void modifyList(List<? extends I> l) {
// ...
}
The type should be a wildcard, meaning any type, as long as its superclass is (...), or in this case, the I class.
Upvotes: 9