有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

Iterator<?> children = element.getChildElements();

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

@SuppressWarnings("unchecked")
Iterator<ActualObject> currentChildren = (Iterator<ActualObject>)currentElement.getChildElements();

Iterator<?> children = element.getChildElements();
while (null != children && children.hasNext()) {
  ActualObject child = (ActualObject)children.next(); //Possible 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;
    ...
}

这似乎过于冗长。有没有一种更好但同样“安全”的方法来遍历原始迭代器

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


共 (4) 个答案

  1. # 1 楼答案

    Guava通过其Iterators.filter(Iterator<?>, Class<T>)方法使这一过程变得简单。它返回一个不可修改的Iterator<T>,基本上只跳过给定迭代器中不是T类型实例的每个元素:

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

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

  2. # 2 楼答案

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

  3. # 3 楼答案

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

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

  4. # 4 楼答案

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

    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);
    }
    

    我想说这还不错

    编辑:

    if块下面可能也应该有一个else块。 大致如下:

    else{
        log.warn("Expected type: " + ActualObject.class + ", but got " + obj);
    }