Search code examples
javagenericsiterator

How can Iterator<SubClass> be cast to Iterator<SuperClass>?


If SubClass extends SuperClass, Iterator<SubClass> cannot be cast to Iterator<SuperClass>. However, I have the situation that the Interfaces demandIterator<SuperClass and supply Collection<SubClass> and cannot be changed.

I've seen answers regarding lists, because you can't add a SuperClass-Object to a list of SubClass-Objects, but shouldn't it be safe for iterators, since you're only reading? Is there a way to cast this?

public Iterator<SuperClass> list(String keyword) {
    Collection<SubClass> result = service.searchByKeyword(keyword);
    return result.iterator();
}

Solution

  • I would recommend @khelwood's suggestion to just cast to (Iterator). However, if you don't like to see the warnings about usage of raw types, and you don't like suppressing warnings, then you can create an iterator of the required SuperClass type which forwards its methods to the SubClass iterator:

    public Iterator<SuperClass> list(String keyword) {
        Collection<SubClass> result = service.searchByKeyword(keyword);
    
        return new Iterator<>() {
            final Iterator<SubClass> it = result.iterator();
    
            @Override
            public boolean hasNext() {
                return it.hasNext();
            }
    
            @Override
            public SuperClass next() {
                // it.next() is a SubClass, therefore also a SuperClass
                return it.next();
            }
        };
    }
    

    It's probably overkill, but it's one way of making the compiler happy.