3

I have a class B which extends A. A stores a list of AItem and B stores a list of BItem

In 'A' I have an ArrayList which uses [? extends AItem] .

I assume this means that I can use this ArrayList for objects of any type that extends AItem.

So in my B class I have a method add(..) which adds a BItem to the items.

I assumed this would work because the items arrayList can hold a list of any object that extends from AItem.

import java.util.ArrayList;

class A {
    public ArrayList<? extends AItem> items;
}

public class B extends A{

    public void add(BItem i) {

        this.items.add(i); //compile error here
    } 
}

//items :
class AItem {}
class BItem extends AItem{}

How would I get this to work?

My compile error looks like this :

The method add(capture#2-of ? extends AItem) in the type ArrayList is not applicable for the arguments (BItem)

M A
  • 65,721
  • 13
  • 123
  • 159
Oliver Watkins
  • 10,301
  • 19
  • 83
  • 168
  • You can't add items to an list of unknown type – Ian2thedv Apr 25 '16 at 13:43
  • 1
    Possible duplicate of [How can I add to List extends Number> data structures?](http://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures) – Ian2thedv Apr 25 '16 at 13:46
  • Very good question. I stay tunned for answers but I think that you need to initialize the arrayList with some class. – jabujavi Apr 25 '16 at 13:46
  • You need to use `ArrayList super AItem>` [read this](http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java) for more information. – ArcticLord Apr 25 '16 at 13:48

3 Answers3

6

You probably don't need to use generics here. Having the list of type AItem in class A should be fine (I would also declare it of type List instead of ArrayList for best practices):

class A {
    public List<AItem> items;
}

class B extends A {

    public void add(BItem i) {

        this.items.add(i);
    } 
}

The problem with ? extends AItem is that the compiler cannot guarantee that the actual type of the elements is AItem or BItem. It could be another subclass CItem in which case the type safety is broken.

There is another approach to designing the class hierarchy with generics, in which you set the type parameter in the parent class and set it to the appropriate subclass (BItem) in the extended class B:

class A<T extends AItem> {
    public ArrayList<T> items;
}

class B extends A<BItem>{

    public void add(BItem i) {

        this.items.add(i);
    } 
}
M A
  • 65,721
  • 13
  • 123
  • 159
2

Try replacing extends with super

import java.util.ArrayList;

class A {
    public ArrayList<? super AItem> items;
}

public class B extends A{

    public void add(BItem i) {

        this.items.add(i); //compile error here
    } 
}

//items :
class AItem {}
class BItem extends AItem{}

You may find more details about the reason behind this behavior, here

Community
  • 1
  • 1
JavaHopper
  • 5,537
  • 1
  • 18
  • 27
1

you can use

public ArrayList<? super AItem> items; 

and you can add to the list now

but you will not be able to do

public class B extends A{
 .....

   public BItem getOne(int idx) {
     return this.items.get(idx);

   }
}

jvm doesn't know what will be actually in the list.

you can generify the A class

class  A<T> {
    public ArrayList<T> items;
}

then define your B class as

public class B extends A<BItem>{

    public void add(BItem i) {

        this.items.add(i); 
    } 
}
Josef Procházka
  • 1,215
  • 2
  • 9
  • 28