在Java中安全地遍历原始迭代器?

在Java中安全地遍历原始迭代器?,java,generics,iterator,types,Java,Generics,Iterator,Types,我使用的第三方库返回原始迭代器,例如 Iterator<?> children = element.getChildElements(); Iterator children=element.getChildElements(); 我知道实际的类型,但我不一定相信第三方lib将来会坚持使用它。有两种(我能想到的)有点风险的方法来解决这个问题: @SuppressWarnings("unchecked") Iterator<ActualObject> currentCh

我使用的第三方库返回原始迭代器,例如

Iterator<?> children = element.getChildElements();
Iterator children=element.getChildElements();
我知道实际的类型,但我不一定相信第三方lib将来会坚持使用它。有两种(我能想到的)有点风险的方法来解决这个问题:

@SuppressWarnings("unchecked")
Iterator<ActualObject> currentChildren = (Iterator<ActualObject>)currentElement.getChildElements();
@SuppressWarnings(“未选中”)
迭代器currentChildren=(迭代器)currentElement.getChildElements();

Iterator children=element.getChildElements();
while(null!=children&&children.hasNext()){
ActualObject child=(ActualObject)children.next();//可能的ClassCastException@runtime
...
}
我能想到的遍历这种迭代器的唯一“安全”方法是:

Iterator<?> children = element.getChildElements();
while (null != children && children.hasNext()) {
  Object obj = children.next();
  ActualObject child = null;
    if (obj instanceof ActualObject)
      child = (ActualObject)obj;
    ...
}
Iterator children=element.getChildElements();
while(null!=children&&children.hasNext()){
Object obj=children.next();
ActualObject子对象=null;
if(实际对象的对象实例)
子对象=(实际对象)对象;
...
}
这似乎过于冗长。是否有一种更好但同样“安全”的方法来遍历原始迭代器?

编辑:我意识到我可以在else块中捕获/记录异常,我正在寻找(希望)一种与ColinD在下面提到的Java语言等价的语言。

通过它的方法使这变得简单。它返回一个不可修改的
迭代器
,它基本上只跳过给定迭代器中不是
t
类型实例的每个元素:

Iterator<ActualObject> children = Iterators.filter(element.getChildElements(),
    ActualObject.class);
Iterator children=Iterators.filter(element.getChildElements(),
类);

显然,您可以遍历生成的迭代器,而无需将每个元素强制转换为
ActualObject
,也无需担心
ClassCastException

处理它的简单方法就是强制转换它,并确保如果类型在将来发生更改,将引发异常并通知您。您将要检查,无论您如何记录异常,异常都是有效的,并且异常将进入日志文件。例外的存在是为了告诉你一些事情不是你所期望的,让他们做他们的工作


如果您悄悄地跳过了非预期类型的元素,那么您可能会丢失所需的数据,这对我来说不是一个好的解决方案。

您的上一个版本似乎是一个不错的选择,但我想我们可以稍微改进一下:

Iterator<?> children = element.getChildElements();
// no null check needed. If an api that supposedly
// returns an iterator actually returns null, it's a bad
// API, don't use it
while (children.hasNext()) {
    Object obj = children.next();
    if (obj instanceof ActualObject)
        doStuffWith((ActualObject)obj);
    // we know it's of the right type so we might
    // as well put the cast in the method call.
}

如果遇到迭代器返回的对象不是
ActualObject
的实例,那么听起来像是要停止执行并抛出异常,那么我将强制转换它,并使用catch块来处理可能的
ClassCastException

谢谢,这很有趣,但不幸的是,我不能选择使用番石榴。@Segfault:那么请阅读源代码并检查他们是如何做到的。我怀疑他们做了与上一个示例相同的事情,但只是将其提取到包装器对象中。是的,它确实有效地做了与第二个示例相同的事情,虽然它构建在它们的谓词/筛选代码的其余部分上。@pkaeding-非常重要:如果迭代器返回的对象不是
ActualObject
的实例,您希望发生什么?如果子对象的类型不是ActualObject,应该怎么办?如果不需要继续,我认为捕获ClassCastException可能是最干净的方法。您可以记录类型不匹配并继续。@pkaeding&@Gangadhar-我会抛出一个异常。Guava方法(就像Guava中的许多东西一样)的存在使得在核心Java中更容易、更简洁地执行一些相当冗长的操作,因此我不希望在JDK中找到任何等价的东西。您对空检查的看法是正确的,我将删除它。这是一个糟糕的API,在很多方面,问题并不能证明这一点。我迫不及待地想再也不用它了。
Iterator<?> children = element.getChildElements();
// no null check needed. If an api that supposedly
// returns an iterator actually returns null, it's a bad
// API, don't use it
while (children.hasNext()) {
    Object obj = children.next();
    if (obj instanceof ActualObject)
        doStuffWith((ActualObject)obj);
    // we know it's of the right type so we might
    // as well put the cast in the method call.
}
Iterator<?> children = element.getChildElements();
while (children.hasNext()) {
    Object obj = children.next();
    if (obj instanceof ActualObject)
        doStuffWith((ActualObject)obj);
}
else{
    log.warn("Expected type: " + ActualObject.class + ", but got " + obj);
}