2012-01-24 31 views
4

在某些频率下,我发现自己编写的API提供了一个由网络连接支持的Iterator<Foo>。该实现打开网络连接,从流中读取信息,并将该信息反序列化为Foo,以传递给调用者。不幸的是,总是有可能出现IOException,并且还需要优雅地关闭网络连接(当调用者读取最后的Foo时可以自动关闭,但如果没有发生,该怎么办?)。支持网络连接的Java Iterator

已经有几个问题如何应对检查的异常,将在Iterator实现抛出(herehere),并接受建议是“在选中RuntimeException S环绕他们。”同时为了允许关闭网络连接,我们可以实现Closeable。所以,我们最终是这样一个乖巧异常检查来电者:

Iterator<Foo> iter = null; 
try { 
    iter = getFooIterator(); 
    while(iter.hasNext()) { 
     Foo foo = iter.next(); 
     // do something with foo 
    } 
} 
catch(RuntimeException e) { 
    if(e.getCause() instanceof IOException) { 
     // do something with the IOException 
    } 
    else throw e; 
} 
finally { 
    if(iter instanceof Closeable) try { ((Closeable)iter).close(); } catch(IOException e) {} 
} 

,它似乎像这样一个不错的主意,实现Iterator。有没有更好的办法?

+0

如果您正在使用Java 7,还可以考虑使用'AutoCloseable'并在try语句中打开资源,例如'try(iter = getFooIterator();){...}'(但迭代器必须实现'AutoCloseable')。 – Thomas

+0

您可能还想考虑关闭迭代器方法中的连接(例如在'next()'或'hasNext()')中,然后抛出异常。这样迭代器的用户就不必担心关闭迭代器(从而底层连接),只需要处理异常。 – Thomas

+0

不得不承认,我不是一个大的迭代器人(我使用集合和简单的数组一吨)。为什么你想用这些开放式问题来返回一个Iterator,而不是一个Collection,这会是一个更简单的API?你收回收集,并且一切都关闭,任何将要发生的异常都会发生。我想我知道答案,但想问...... – user949300

回答

1

IMO的第一步就是将其包含在实现或应用程序特定的异常中,无需捕获通用的RuntimeException或检查根本原因。

我会考虑一个具体的实现,以避免可关闭的检查,并包装IOException

NetworkIterator<Foo> iter = null; 
try { 
    iter = getFooIterator(); 
    while (iter.hasNext()) { 
     Foo foo = iter.next(); 
     // do something with foo 
    } 
} catch (NetworkIteratorExceptiom e) { 
    // do something with the IOException 
} finally { 
    iter.close(); 
} 

我可能不会给它的方法,使样板走了,但我会动心;大致如下:

NetworkIterator<Foo> iter = new IteratorThang<Foo>() { 
    @Override public void each(Foo foo) { 
     // Do something with foo 
    } 
}; 
+0

好主意。事实上,我想知道是否真的有利于实现java.util.Iterator,而不是具有可以抛出检查异常的特定Iterator等。有很多'Iterator'的消费者吗? –

+0

@ RobertTupelo-Schneck各种各样的东西都会消耗迭代器;考虑类似[番石榴的'任何'方法](http://stackoverflow.com/a/8991373/438992) - 像这样的惰性迭代有很多用例。它基本上和长时间的计算一样,只有在实际需要时才会生成后续值(可能是缓存) - 它只是从网络而不是数学(或其他)。 –