Jackson 的
objectMapper.readValues(...)
返回一个 MappingIterator
类,该类同时实现 Closeable
和 Iterator
:
public class MappingIterator<T> implements Iterator<T>, Closeable {...}
我使用它来反序列化 JSONL,但我不希望我的方法与 Jackson 特定对象绑定,因此我创建了一个
CloseableIterator
来代替它来实现两者:
public interface CloseableIterator<T> extends Iterator<T>, Closeable {...}
我希望我的方法返回
CloseableIterator
,而不是直接暴露MappingIterator
:
CloseableIterator<FooBar> readFooBars(...) {
return objectMapper.readValues(...);
}
但是,编译器不会让我在不添加未经检查的强制转换的情况下编译它,这似乎没有必要。 有没有办法将一个对象转换为一个接口,进而扩展多个接口?
不幸的是,即使通过铸造也是不可能的。转换将在运行时失败,因为返回的类型未实现您的接口,即使其方法与
MappingIterator
的方法相同。但我想到了一些解决方法。
一个选择是使用您的界面作为一种委托给 Jackson 实现的装饰器:
CloseableIterator<FooBar> readFooBars(...) {
var iterator = objectMapper.readValues(...);
return new CloseableIterator<>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public FooBar next() {
return iterator.next();
}
@Override
public void close() throws IOException {
iterator.close();
}
};
}
(如果你有 Guava,你可以使用
ForwardingIterator
来稍微减少样板代码。)
或者,您可以返回一个多边界通用包装类封装您的迭代器:
class Wrapper<T extends Iterator<FooBar> & Closeable> {
final T result;
Wrapper(T result) {
this.result = result;
}
}
Wrapper<?> readFooBars(...) {
return new Wrapper<>(objectMapper.readValues(...));
}