Jackson's objectMapper.readValues(...)
returns a MappingIterator
class, that implements both Closeable
and Iterator
:
public class MappingIterator<T> implements Iterator<T>, Closeable {...}
I'm using it to deserialize a JSONL, but I don't want my method to be tied to Jackson specific objects, so I've created an CloseableIterator
instead that implements both:
public interface CloseableIterator<T> extends Iterator<T>, Closeable {...}
I want my method to return CloseableIterator
, instead of directly exposing MappingIterator
:
CloseableIterator<FooBar> readFooBars(...) {
return objectMapper.readValues(...);
}
However, the compiler won't let me compile it without adding an unchecked cast, which seems unnecessary. Is there a way to cast an object into an interface that in turn extends multiple interfaces?
Unfortunately, it's not possible even with casting. The cast would fail at runtime because the returned type does not implement your interface, even if its methods are identical to MappingIterator
's.
A simple workaround is to return a private implementation of your interface that delegates to the Jackson iterator:
private static class JacksonCloseableIterator<T> implements CloseableIterator<T> {
private final MappingIterator<T> iterator;
JacksonCloseableIterator(MappingIterator<T> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
return iterator.next();
}
@Override
public void close() throws IOException {
iterator.close();
}
}
(If you have Guava, you can extend ForwardingIterator
to reduce the boilerplate somewhat.)
See here for an alternative approach using generics with multiple bounds.