Reputation: 68942
I'm currently facing an issue with base and subclasses.
While having a single object as parameter (method single) the compiler doesn't complain.
But if it comes to lists the compiler forces me to declare the list as <? extends Base>
After that I'm no longer allowed to add objects of the base type to that list.
How can I use both types (Base and Subclass) in one list?
public class Generics {
class Base { }
class Sub extends Base{ }
interface I {
public void list( List<Sub> list );
public void single( Sub p);
}
class C implements I {
public void list( List<Sub> list) { }
public void single( Sub p) { }
}
void test() {
C c = new C();
c.single( new Sub() );
c.list( new ArrayList<Base>() ); // The method list(List<Generics.Sub>) in the type Generics.C is not applicable for the arguments (ArrayList<Generics.Base>)
}
public static void main( String[] args) {
Generics g = new Generics();
g.test();
}
}
Upvotes: 0
Views: 136
Reputation: 33534
Below are the 2 ways to do it....
public void inTake(List<? extends Base> list){
}
Or
public T extends Base void inTake(List<T> list){
}
Upvotes: 1
Reputation: 17309
Change:
public void list(List<Sub> list);
to:
public void list(List<? extends Base> list);
Using just List<Base>
will give you compiler errors like this one:
public static void main(String[] args) {
List<Sub> subs = new ArrayList<Sub>();
doSomethingWith(subs); // The method doSomethingWith(List<Base>) in the type Main is not applicable for the arguments (List<Sub>)
}
private static void doSomethingWith(List<Base> bases) {
// Do something with bases
}
If all you're going to pass is List<Base>
to doSomethingWith
, then this point is moot, since this won't give you a compiler error. If you want to pass lists that are of a specific type (such as List<Sub>
above), then you need to change doSomethingWith
to:
private static void doSomethingWith(List<? extends Base> bases) {
This fixes the problem. You could also do it at the caller lever (but it's a bit messier):
List<Sub> subs = new ArrayList<Sub>();
doSomethingWith(new ArrayList<Base>(subs));
One issue with the wildcard (?
) approach is that you can't add new items to the list. To do that, you need something like:
private static <B extends Base> void doSomethingWith(List<B> bases) {
And then add only B
instances to bases
.
Upvotes: 1
Reputation: 46209
Just declare all your lists as
List<Base> list;
Then you can add both Base
objects and objects of any subclass.
Upvotes: 1