Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

casting Collection<SomeClass> to Collection<SomeSuperClass>

I'm sure this has been answered before, but I really cannot find it.

I have a java class SomeClass and an abstract class SomeSuperClass. SomeClass extends SomeSuperClass.

Another abstract method has a method that returns a Collection<SomeSuperClass>. In an implementation class, I have a Collection<SomeClass> myCollection

I understand that I cannot just return myCollection, because Collection<SomeClass> does not inherit from Collection<SomeSuperClass>. Nevertheless, I know that everything in myCollection is a SomeSuperClass because after all, they're SomeClass objects which extend SomeSuperClass.

How can I make this work?

I.e. I want

public class A
{
  private Collection<SomeClass> myCollection;

  public Collection<SomeSuperClass> getCollection()
  {
    return myCollection; //compile error!
  }
}

The only way I've found is casting via a non-generic type and getting unchecked warnings and whatnot. There must be a more elegant way, though? I feel that also using Collections.checkedSet() and friends are not needed, since it is statically certain that the returned collection only contains SomeClass objects (this would not be the case when downcasting instead of upcasting, but that's not what I'm doing). What am I missing?

Thanks!

like image 552
skrebbel Avatar asked Mar 17 '10 09:03

skrebbel


4 Answers

Will Collection<? extends SomeSuperClass> not do what you want?

like image 180
ishmeister Avatar answered Nov 15 '22 00:11

ishmeister


You can't do this. You have a Collection<SomeClass> and wish to return a Collection<SuperClass>

Now imagine that someone has your returned Collection - and they try to insert a different subclass of SuperClass, SomeOtherClass. This should be allowed on your SuperClass collection - but it can't because it's actually a Collection<SomeClass>, unbeknownst to anyone but the private member of A.

like image 30
Steven Schlansker Avatar answered Nov 15 '22 01:11

Steven Schlansker


Java 8 now offers a neater way of doing it using lambdas: you can use the map() and collect() functions to cast the objects to your super class. A solution for your example would look like this:

public class A
{
    private Collection<SomeClass> myCollection;

    public Collection<SomeSuperClass> getCollection()
    {
        return myCollection.stream().map(x -> (SomeSuperClass) x).collect(Collectors.toList());
    }
}

You can also use other Collectors if needed.

like image 7
Vlad Schnakovszki Avatar answered Nov 15 '22 02:11

Vlad Schnakovszki


If you create a new collection of the correct type you can populate it using the old collection

public Collection<SomeSuperClass> getCollection()
{
    return new ArrayList<SomeSuperClass>(myCollection); 
}
like image 1
Konstantin Avatar answered Nov 15 '22 01:11

Konstantin