13

So I have this method:

protected void collectSelectedItems(ListSelectionModel lsm, 
         Collection<? super MyItemClass> result) {
    for (int i : GUI.getSelectionIndices(lsm))
    {
        result.add(getItemByDisplayIndex(i));
    }
}

I'd like to return the collection instead of having a void method:

protected <T super MyItemClass> Collection<T> 
  collectSelectedItems(ListSelectionModel lsm, Collection<T> result) {
    for (int i : GUI.getSelectionIndices(lsm))
    {
        result.add(getItemByDisplayIndex(i));
    }
    return result;
}

with the intent of doing something like this (where MyItemClass extends MyItemBaseClass):

List<MyItemBaseClass> list = 
   collectSelectedItems(lsm, new ArrayList<MyItemBaseClass>());

but I get a syntax error on the super:

Syntax error on token "super", , expected

What gives? Can I fix this?

Jeff Axelrod
  • 27,676
  • 31
  • 147
  • 246
Jason S
  • 184,598
  • 164
  • 608
  • 970

3 Answers3

8

Here's one link that explains why this is not allowed:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ107

It basically just says that use super in type parameters "does not buy you anything", since if this is allowed, erasure will probably just erase it to Object, which does not make much sense.

zw324
  • 26,764
  • 16
  • 85
  • 118
  • 1
    It "buys you something" if you want to declare your method to take a `Comparator super Widget>` though, because a `Comparator` would be perfectly capable of sorting all subclasses of `Object`. But yeah, for collections, it's almost always the wrong thing to do. – Hakanai Dec 04 '14 at 00:08
  • 1
    That's not what the linked page says - it explicitly says that if super were allowed in _method_ declarations, that would help create type-safe generic methods. Right now the example I bumped into is Optional's orElse: it only accepts the same type as the Optional, even though it would often make perfect sense to say `Optional optional = ...; Supertype result = optional.orElse(supertypeInstance);` – laszlok May 24 '18 at 11:12
2

Here are two ideas. The first only returns a generic Collection, the second returns the actual result-type:

public <T, S extends T> Collection<T> ver1(Collection<S> src, Collection<T> dst)
{
    dst.addAll(src);
    return dst;
}

public <U, T extends Collection<U>, S extends U> T ver2(Collection<S> src, T dst)
{
    dst.addAll(src);
    return dst;
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

well, I didn't answer my question exactly, but this is an acceptable solution for my problem:

protected <T extends Collection<? super MyItemClass>> 
  T collectSelectedItems(ListSelectionModel lsm, T result) {
    for (int i : GUI.getSelectionIndices(lsm))
    {
        result.add(getItemByDisplayIndex(i));
    }
    return result;
}
Jason S
  • 184,598
  • 164
  • 608
  • 970