Search code examples
javagenericscollectionstoarraysubtyping

Java Collection::toArray with subclasses


Is there a way to use the Collection::toArray(T[]) method when you only know the subtype of the collection?

Take this example:

void initList(Collection<? extends AorB> data) {
    JList<? extends AorB> aorb_jlist = new JList<>();
    aorb_jlist.setListData(data.toArray(new T<? extends AorB>[data.size()]));
}

abstract class AorB {}
class A extends AorB {}
class B extends AorB {}

(I just put T there for illustration, I know that wouldn't work)

All I know about the Collection is that it is a subclass of AorB, but it could be either. The JList accepts <? extends AorB> as its type, but the setListData method needs an array, and Collection::toArray needs input.

Am I barking up the wrong tree with toArray? Is there an easy, efficient way to convert this Collection to array without manually iterating over it?

Edit to answer @PaulBoddington:

You can't change <? extends AorB> to <AorB> because then the method won't receive a Collection of subtypes:

Example:

void initList(Collection<AorB> data) {
    JList<AorB> aorb_jlist = new JList<>();
    aorb_jlist.setListData(data.toArray(new AorB[data.size()]));
}

abstract class AorB {}
class A extends AorB {}
class B extends AorB {}

public static void main(String[] args) {
    LinkedList<A> a_list = new LinkedList<>();
    initList(a_list);
}

throws an error:

incompatible types: LinkedList<A> cannot be converted to Collection<AorB>

Solution

  • Leave the collection as Collection<? extends AorB>, but make the JList a JList<AorB>:

    void initList(Collection<? extends AorB> data) {
        JList<AorB> aorb_jlist = new JList<>();
        aorb_jlist.setListData(data.toArray(new AorB[data.size()]));
    }