java 实现java.lang.Iterator时异常怎么办

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2205773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:02:18  来源:igfitidea点击:

What to do of exceptions when implementing java.lang.Iterator

javaexceptioniterator

提问by Vincent Robert

The java.lang.Iteratorinterface has 3 methods: hasNext, nextand remove. In order to implement a read-only iterator, you have to provide an implementation for 2 of those: hasNextand next.

java.lang.Iterator接口有 3 个方法:hasNext,nextremove。为了实现只读迭代器,您必须为其中两个提供一个实现:hasNextnext

My problem is that these methods does not declare any exceptions. So if my code inside the iteration process declares exceptions, I must enclose my iteration code inside a try/catch block.

我的问题是这些方法没有声明任何异常。因此,如果我在迭代过程中的代码声明了异常,我必须将我的迭代代码包含在一个 try/catch 块中。

My current policy has been to rethrow the exception enclosed in a RuntimeException. But this has issues because the checked exceptions are lost and the client code no longer can catch those exceptions explicitly.

我目前的政策是重新抛出包含在RuntimeException. 但这有问题,因为检查过的异常丢失了,客户端代码不再能显式地捕获这些异常。

How can I work around this limitation in the Iterator class?

如何在 Iterator 类中解决此限制?

Here is a sample code for clarity:

为了清楚起见,这是一个示例代码:

class MyIterator implements Iterator
{
    @Override
    public boolean hasNext()
    {
        try
        {
            return implementation.testForNext();
        }
        catch ( SomethingBadException e ) 
        {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean next()
    {
        try
        {
            return implementation.getNext();
        }

        catch ( SomethingBadException e ) 
        {
            throw new RuntimeException(e);
        }
    }

    ...
}

采纳答案by helios

I've implemented a lot of Iterator, sometimes on top of with-check-exception iterators (ResultSet is conceptually a record iterator, InputStream y conceptually a byte iterator) and so on. It's very very nice and handy (you can implement pipe & filters architecture for a LOT of things).

我已经实现了很多迭代器,有时在带检查异常迭代器之上(ResultSet 概念上是一个记录迭代器,InputStream y 概念上是一个字节迭代器)等等。它非常好用(你可以为很多东西实现管道和过滤器架构)。

If you prefer to declare your exceptions, then declare a new type of Iterator (ExceptionIterator, it would be like Runnable and Callable). You can use it along or your code but you can't compose it with outside components (Java Class Library or 3d party libs).

如果你更喜欢声明你的异常,那么声明一个新类型的迭代器(ExceptionIterator,它就像 Runnable 和 Callable)。您可以将其与您的代码一起使用,但您不能将其与外部组件(Java 类库或 3d 方库)组合在一起。

But if you prefer to use super-standard interfaces(like iterator) to use them anywhere, then use Iterator. If you know your Exceptions will be a condition for stop your processing, or you don't mind a lot... use them.

但是如果你更喜欢使用超标准接口(如迭代器)在任何地方使用它们,那么使用迭代器。如果您知道您的异常将成为停止处理的条件,或者您并不介意……使用它们。

Runtime exceptions are not so terrible.By example. Hibernate use them to implement proxies and stuff like that. They have to except DB exceptions but can't declare them in their implementations of List.

运行时异常并没有那么可怕。举个例子。Hibernate 使用它们来实现代理和类似的东西。他们必须排除数据库异常,但不能在他们的 List 实现中声明它们。

回答by Rorick

You should rethrow exception as custom runtime exception, not generic one, for instance SomethingBadRuntimeException. Also, you can try exception tunneling.

您应该重新抛出异常作为自定义运行时异常,而不是通用异常,例如SomethingBadRuntimeException。此外,您可以尝试异常隧道

And I'm assured that forcing client to deal with exceptions by making them checked is a bad practice. It just pollutes your code or forces to wrap exceptions with runtime ones or force to process them in place of call but not centralized. My policy is to avoid using checked exceptions as much as possible. Consider IOExceptionon Closable.close(): is it useful or convenient? Cases when it is are very rare, but every Java developer in the world is forced to deal with it. Most often it is swallowed or logged at best. And imagine how much this adds to code size! There's some posts about checked exceptions from their dark side:

而且我确信通过检查异常来强制客户端处理异常是一种不好的做法。它只会污染您的代码或强制使用运行时异常包装异常或强制处理它们而不是调用而不是集中处理。我的政策是尽可能避免使用受检异常。考虑IOExceptionClosable.close():这是有用的还是方便?这种情况非常罕见,但世界上的每个 Java 开发人员都被迫处理它。大多数情况下,它最多被吞下或记录下来。想象一下这会增加多少代码大小!有一些帖子是关于受检异常的阴暗面的:

  1. "Does Java need Checked Exceptions?" by Bruce Eckel
  2. The Trouble with Checked Exceptions A Conversation with Anders Hejlsberg, by Bill Venners with Bruce Eckel
  3. Java Design Flaws, C2 wiki
  1. “Java 需要检查异常吗?” 通过布鲁斯·埃克尔
  2. Checked Exceptions 的麻烦与 Anders Hejlsberg 的对话,Bill Venners 与 Bruce Eckel
  3. Java 设计缺陷,C2 wiki

There are cases when checked exceptions comes to rescue. But in my opinion they are rare and usually concern to implementation of some specific module. And they don't give very much profit.

在某些情况下,检查异常可以解决问题。但在我看来,它们很少见,通常与某些特定模块的实现有关。而且他们的利润并不多。

回答by Stephen C

As someone who likesJava checked exceptions, I think that the problem (Java design flaw if you will) is that the standard libraries don't support a generic Iterator type where the nextmethod throws a checked exception.

作为喜欢Java 检查异常的人,我认为问题(如果您愿意的话是 Java 设计缺陷)是标准库不支持该next方法抛出检查异常的通用 Iterator 类型。

The code base for Sesamehas an Iterator variant class called Iterablethat does just that. The signature is as follows:

Sesame的代码库有一个称为Iterable的 Iterator 变体类,它就是这样做的。签名如下:

Interface Iteration<E,X extends Exception>

Type Parameters:
    E - Object type of objects contained in the iteration.
    X - Exception type that is thrown when a problem occurs during iteration.

This seems to work in the limited context of Sesame, where specific subclasses are used that "fix" the exception type parameter. But (of course) it doesn't integrate with the standard collection types, Java 5's new forloop syntax, and so on.

这似乎在 Sesame 的有限上下文中起作用,其中使用特定子类来“修复”异常类型参数。但是(当然)它没有与标准集合类型、Java 5 的新for循环语法等集成。

回答by ishmeister

hasNext should not really throw an exception - it should check that it is ok to proceed and return a boolean value on that basis (I would log any underlying exceptions with a logger). I would throw a RuntimeException if next fails (and log the checked exception with a logger). Next should not fail in normal conditions if the test was ok and if the test fails you should not call next (hence runtime exception).

hasNext 不应该真的抛出异常——它应该检查是否可以继续并在此基础上返回一个布尔值(我会用记录器记录任何潜在的异常)。如果下一次失败,我会抛出一个 RuntimeException(并用记录器记录已检查的异常)。如果测试正常,Next 不应在正常情况下失败,如果测试失败,则不应调用 next(因此运行时异常)。

回答by Marcel Hymanwerth

If your implementation doesn't have the properties required by the Iterator interface, why do you want to use it?

如果您的实现没有 Iterator 接口所需的属性,为什么要使用它?

I see no other solution than the RuntimeException (with it's issues).

除了 RuntimeException(有问题),我看不到其他解决方案。

回答by bpow

This question was asked a long time ago, but I would like to have feedback on a pattern that may be useful here. An additional interface or class ExceptionHandlercould be composed within the class which implements Iterator and could be implemented by the client to address the exceptions as desired.

很久以前就有人问过这个问题,但我想就一种可能在这里有用的模式提供反馈。ExceptionHandler可以在实现 Iterator 的类中组合一个额外的接口或类,并且可以由客户端实现以根据需要解决异常。

public interface ExceptionHandler {
    // Log, or rethrow, or ignore...
    public Object handleException(Exception e);
}

Implementing classes could do something like these:

实现类可以做这样的事情:

public class ExceptionRethrower implements ExceptionHandler {
    @Override
    public Object handleException(Exception e) {
        throw new RuntimeException(e);
    }
}

public class ExceptionPrinter implements ExceptionHandler {
    @Override
    public Object handleException(Exception e) {
        System.err.println(e);
        return e;
    }
}

For an iterator that reads from a file, the code may look something like this:

对于从文件读取的迭代器,代码可能如下所示:

public class MyReaderIterator implements Iterator<String> {
    private final BufferedReader reader;
    private final ExceptionHandler exceptionHandler;
    public MyReaderIterator(BufferedReader r, ExceptionHandler h) {
        reader = r;
        exceptionHandler = h;
    }
    @Override
    public String next() {
        try {
            return reader.readLine();
        } catch (IOException ioe) {
            Object o = exceptionHandler.handleException(ioe);
            // could do whatever else with o
            return null;
        }
    }
    // also need to implement hasNext and remove, of course
}

What do people think? It is worth this level of indirection, or is it a layering violation and just plain too complicated? The name of the interface may not be exactly appropriate (perhaps ExceptionProcessor or ExceptionInterceptor since it can interact with but not fully handle the exception, there still needs to be some handling in the class into which it is composed).

人们怎么看?值得这种间接级别,还是违反分层并且过于复杂?接口的名称可能不完全合适(可能是 ExceptionProcessor 或 ExceptionInterceptor 因为它可以与异常交互但不能完全处理异常,仍然需要在组成它的类中进行一些处理)。

I agree that this all just seems like a workaround to the fact that Iterator.next() wasn't declared to throw exceptions, and makes me pine for generators and python's exception model.

我同意这一切似乎都是解决 Iterator.next() 未声明抛出异常这一事实的一种解决方法,这让我对生成器和 python 的异常模型感到厌烦。

回答by nuoritoveri

If you really don't want to use Runtime exception, you can use NoSuchElementException. You are allowed to use it in overridden next()method because it is declared to be thrown in Iteratordefinition (I tried this and the code compiled). But you should consider whether it is semanticallyvalid for your case.

如果你真的不想使用运行时异常,你可以使用NoSuchElementException. 您可以在重写的next()方法中使用它,因为它被声明为在Iterator定义中抛出 (我试过这个并编译了代码)。但是您应该考虑它在语义上是否对您的情况有效。

回答by boumbh

In my mind, iterators are meant to iterate, they are not meant to compute, hence the absence of throwson the next()method.

在我看来,迭代器是用来迭代的,而不是用来计算的,因此方法throws上没有next()

You are asking how to use the interface to do something it was not designed for.

您问的是如何使用界面来做一些它没有设计的事情。

Still, if the Iteratoris aimed to be used by yourself (which is generally a bad assumption), you could define a public safeNext()method like this:

尽管如此,如果Iterator旨在供您自己使用(这通常是一个错误的假设),您可以定义一个公共safeNext()方法,如下所示:

public Element safeNext() throws YourCheckedException {
    ...
}

@Override
public Element next() {
    try {
        return safeNext();
    } catch (YourException e) {
        throw new YourRuntimeException("Could not fetch the next element", e);
    }
}

Then, when using the Iteratoryou can choose to use safeNext()and handle the checked exception, or use next()as you would with any iterators.

然后,在使用 时,Iterator您可以选择使用safeNext()和处理已检查的异常,或者next()像使用任何迭代器一样使用。

In short, you can't have both the convenience of the iterator interface (you can't expect that Iterableobjects will use the safeNext()method), and the checked exception throwing.

总之,你不能同时拥有迭代器接口的便利(你不能指望Iterable对象会使用该safeNext()方法),和被检查的异常抛出。

回答by smnsvane

I usally use

我通常使用

@Override
void remove() {
    throws new UnsupportedOperationException("remove method not implemented");
}

note: UnsupportedOperationException is a RuntimeException

注意:UnsupportedOperationException 是一个 RuntimeException

Since you are properbly aiming for something like

因为你的目标是像

for (IterElem e : iterable)
    e.action();

You will be fine

你会好起来的

回答by finnw

Whatever you do, do notuse this trick :-)

无论你做什么,都不要使用这个技巧:-)

http://blog.quenta.org/2006/11/generic-exceptions.html

http://blog.quenta.org/2006/11/generic-exceptions.html