最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Casting objects into interface that extends multiple interfaces - Stack Overflow

programmeradmin0浏览0评论

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?

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?

Share Improve this question edited Nov 20, 2024 at 0:42 Joseph asked Nov 20, 2024 at 0:35 JosephJoseph 1729 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 4

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.

发布评论

评论列表(0)

  1. 暂无评论