首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果在打开新的IO流之间处理IO流,那么有一个尝试-最终块还是有嵌套的使用资源的尝试流更好呢?

如果在打开新的IO流之间处理IO流,那么有一个尝试-最终块还是有嵌套的使用资源的尝试流更好呢?
EN

Stack Overflow用户
提问于 2015-09-29 15:38:49
回答 2查看 69关注 0票数 2

因此,在某种方法中,我将打开一个新的IO流,对它进行一些处理,然后使用该流作为输入来打开另一个IO流。我不相信我可以使用一个尝试资源块,因为第一个IO流在打开第一个流和第二个流之间。那么,在编码设计的意义上,使用一个尝试捕获--最终块来打开和关闭这些流,还是使用嵌套的具有资源的尝试块来打开和关闭流会更好吗?我知道,如果在第一个和第二个IO流之间没有处理,最好在一个带有资源的尝试块中打开所有三个流。

下面是一个简单的例子:

Try-Catch-Finally

代码语言:javascript
复制
void someMethod(InputStream is) throws SomeException {
   SomeIOStream io1 = null;
   SomeIOStream io2 = null;
   SomeIOStream io3 = null;

   try{
      io1 = new SomeIOStream( someSortOfProcessing() );
      io1.moreStreamProcessing();
      io2 = new SomeIOStream( someSortOfProcessing(io1) );
      io3 = new SomeIOStream (is);
      //do stuff with io2 and io3
   } catch (Throwable t) {
      //Exception Handling
   } finally {
      //closing streams io3, io2, io1, is
   }
}

Try-with-resources

代码语言:javascript
复制
void someMethod(InputStream is) throws SomeException {
   try ( SomeIOStream io1 = new SomeIOStream( someSortOfProcessing() ) ){
      io1.moreStreamProcessing();
      try ( SomeIOStream io2 = new SomeIOStream( someSortOfProcessing(io1) );
            SomeIOStreeam io3 = new SomeIOStream (is); ){
            //do stuff with io2 and io3
      }
   } catch (Throwable t) {
      //Exception Handling
   } finally {
      //closing stream is
   }
}

在我看来,第一种看起来更干净,但第二种更有资源块的优点。当然,的另一个选项是使用io1资源打开初始io1,但是在这个io1块中打开io2和io3。那么,第三种混合方法会比上述两种方法更好吗?

混合进场

代码语言:javascript
复制
void someMethod(InputStream is) throws SomeException {
   SomeIOStream io1 = null;
   SomeIOStream io2 = null;
   SomeIOStream io3 = null;

   try (SomeIOStream io1 = new SomeIOStream( someSortOfProcessing() ) ){
      io1.moreStreamProcessing();
      io2 = new SomeIOStream( someSortOfProcessing(io1) );
      io3 = new SomeIOStream (is);
      //do stuff with io2 and io3
   } catch (Throwable t) {
      //Exception Handling
   } finally {
      //closing streams io3, io2, is
   }
}

另外,作为一个补充问题,我认为关闭InputStream is的唯一方法是将其放在最终块中,这是否正确?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-29 16:30:34

似乎,你不知道用资源的尝试对你有什么好处。它不仅确保close()被调用,还确保在close()失败时,如果有异常,它不会隐藏初始异常,而是使用addSuppressed记录次要异常。

所以相当于

代码语言:javascript
复制
try(Resource r = allocation ) {
    …
}

代码语言:javascript
复制
{
    Resource r = allocation;
    Throwable primary = null;
    try {
        …
    }
    catch(Throwable t) { primary = t; }
    finally {
        if(r != null) try {
            r.close();
        }
        catch(Throwable t) {
            if(primary!=null) primary.addSuppressed(t); else primary=t;
        }
    }
    if(primary!=null) throw primary;
}

现在再想一想,是否用参考资料重新编写任何try语句,手动地这样做,就会产生更清晰的代码。即使没有正确地处理关闭,使用资源语句的嵌套try的替代方案在代码大小上已经更大了,并且更加复杂,并且将变量的范围扩大到超出实际使用范围的范围。

相反,使用嵌套范围中的资源,嵌套try资源语句准确地反映了您正在做的事情。如果您删除可疑的所有捕获部分并关闭传入的资源,它将变得更好。

注意,在罕见的情况下,关闭传入资源可能是可以接受的,例如,如果它是一个private方法,并且行为已经有了详细的记录。但即便如此,你也不应该求助于finally

代码语言:javascript
复制
void someMethod(InputStream incomingIs) throws SomeException {
    try(InputStream is=incomingIs;// it must be documented that we will close incomingIs
        SomeIOStream io1 = new SomeIOStream(someSortOfProcessing()) ) {
        io1.moreStreamProcessing();
        try(SomeIOStream io2 = new SomeIOStream(someSortOfProcessing(io1));
            SomeIOStreeam io3 = new SomeIOStream (is) ) {
            //do stuff with io2 and io3
        }
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-09-29 15:42:17

这可能是基于意见,但我当然更喜欢使用尝试与资源尽可能多。这清楚地显示了可关闭资源使用的范围,从而使程序逻辑更容易理解。如果您担心嵌套的使用资源的尝试块,请考虑将内部块提取到单独的方法中。

另外,如果将流作为参数传递(在示例中为is),关闭它通常不是一个好主意。如果调用者创建了此流,则调用方通常有责任关闭它(最好是使用调用方方法中的try- with语句)。最后,对于Throwable来说很少是个好主意。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32848239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档