9

我试图将一个类的迭代器转换为所述类的子类的迭代器。这给了我一个“不可转换的类型”错误。为什么这是不可能的,最优雅的解决方法是什么?(或者,如果是这样,为什么这是一个坏主意?)

在这种情况下,使用 for-each 循环不是解决方案:我正在尝试实现iterator(),最简单的方法是返回iterator()我的班级之一的字段,但那个没有确切要求类型。我也不能更改我的签名iterator()

public interface SomeoneElsesInterface {
    public Iterator<SomeoneElsesInterface> iterator();
}

public abstract class MyAbstractClass implements SomeoneElsesInterface {
    final MyAbstractClass[] things;
    public MyAbstractClass(SomeoneElsesInterface... things) {
         this.things = (MyAbstractClass[]) things;
    }
}

public class MyClass extends MyAbstractClass {
    public MyClass(MyAbstractClass thing1, MyAbstractClass thing2) {
        super(thing1, thing2);
    }

    public Iterator<SomeoneElsesInterface>() {
        return (Iterator<SomeoneElsesInterface>) Arrays.asList(things).iterator();
    }
}

当然,我可以只更改things. 但是,在这种情况下,我需要在其他地方进行大量演员表。我知道我的构造函数不会被非MyAbstractClasss 的对象调用,但无论如何我都无法更改接口。

4

5 回答 5

5

我认为根据您的问题,您正在尝试执行以下操作:

Iterator<Object> original = ...
Iterator<String> converted = (Iterator<String>)original;

那是对的吗?

如果是这样,不幸的是,这是不可能的。问题是它original可以包含不是Strings 的对象,因此允许该转换会破坏泛型合同,即converted可以包含不是 s 的东西String

我不认为有一个优雅的解决方法。

你说最简单的实现方法iterator()是返回一个实例字段的迭代器,所以我猜你有这样的东西:

class IterableThing implements Iterable<Foo> {
    private Collection<Bar> someStuff;

    public Iterator<Foo> iterator() {
        return (Iterator<Foo>)someStuff.iterator();
    }
}

class Bar {
}
class Foo extends Bar {
}

如果someStuff可以保证只包含 的实例Foo,那么您可以声明someStuff为 aCollection<Foo>而不是 aCollection<Bar>吗?如果不是,那么只返回 的迭代器就没有任何意义,someStuff因为它可能包含一些不是Foo.

我想您需要考虑您实际上可以做出哪些保证。如果您不能保证someStuff只包含Foos 那么您可能必须维护自己的状态,或者someStuff按需过滤内容。

编辑:你已经用代码更新了你的问题。惊人的。

所以看起来你实际上是在尝试在该类型的超类上返回一个迭代器。这让事情变得容易多了。

在您的特定情况下,您可能可以通过以下方式解决它:

return Arrays.<SomeoneElsesInterface>asList(things).iterator();

它会产生一些警告,但这没关系,因为你知道你已经保证了类型安全。

于 2012-07-15T17:26:23.653 回答
5

这看起来就像使用显式类型参数规范一样简单:

public class MyClass extends MyAbstractClass {
    // ...

    public Iterator<SomeoneElsesInterface> iterator() {
      return Arrays.<SomeoneElsesInterface>asList(things).iterator();
    }
}

问题在于Arrays#asList()推断您想要一个类型的列表List<MyAbstractClass>,这将产生一个类型的迭代器Iterator<MyAbstractClass>。由于Iterator的类型参数不是covariant,因此您不能提供需要 an 的Iterator<MyAbstractClass>地方Iterator<SomeoneElsesInterface>。通过强制Arrays#asList()创建一个 type 列表List<SomeoneElsesInterface>,如上所示,您还可以从对 的调用中返回预期的迭代器类型Iterable#iterator()

的作者会更友好地将其方法SomeoneElsesInterface的返回类型指定为.iterator()Iterator<? extends SomeoneElsesInterface>

于 2012-07-15T17:48:29.850 回答
1

使用for-each循环而不是Iterator.

for-eachJava 1.5引入

有关详细信息,请参阅此链接:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

于 2012-07-15T17:09:04.477 回答
0

如果换成Arrays.asList(things)怎么Arrays.asList((SomeoneElsesInterface[]) things)办?一旦数组被转换为正确的类型,列表和迭代器应该跟随。

于 2012-07-15T17:36:42.767 回答
-1

Java for-each 示例(补充 Kumar 答案):

List<String> strings = new ArrayList<String>();
strings.add( "one" );
strings.add( "two" );
strings.add( "three" );

for ( String item : strings ) {
    System.out.println( item );
}
于 2012-07-15T17:11:31.927 回答