通过在子类型上返回迭代器来实现Iterable

时间:2014-10-23 18:44:44

标签: java generics iterable

在以下代码中:

public class Bar { ... }

public class Foo extends Bar { ... }

public class BarIterable implements Iterable<Bar> {

    List<Foo> foos = ...

    @Override
    public Iterator<Bar> iterator() {
        return foos.iterator();  // Error: Type mismatch ...
    }
}

我在指定位置收到错误,因为foos.iterator()返回Iterable<Foo>而不是Iterable<Bar>。不幸的是,简单的演员阵容不起作用:

return (Iterator<Bar>) foos.iterator();  // Error: Cannot cast ...

Java也不允许我将BarIterable的定义更改为

public class BarIterable implements Iterable<? extends Bar> { ...   // Error: A supertype may not specify any wildcard

解决这个问题的好方法是什么涉及实现Iterable<Foo>(Iterable-implementation来自另一个不了解Foo的接口)?

我是否必须自己编写一个“解包”每个值的包装器Iterator类?

1 个答案:

答案 0 :(得分:6)

由于FooBar的子类型,您只需投放List

return ((List<Bar>)(List<? extends Bar>) foos).iterator(); 

并禁止警告。

由Markus A编辑:

或者,您可以使用intermediate-cast-trick直接强制转换迭代器:

return (Iterator<Bar>)(Iterator<? extends Bar>) foos.iterator();

结束编辑


使用Java 8,您可以对元素进行流式处理,并构建List类型的新Bar

@Override
public Iterator<Bar> iterator() {
    return foos.stream().<Bar>map((foo) -> foo /* considered a Bar */).collect(Collectors.toList()).iterator();  
}

但是你要做的很多中间操作只是为了从超类型的角度来看List