2010-10-22 68 views
1

由于我公司的使用Eclipse和使用Eclipse的代码自动修复的政策,下面的代码模式过度地出现在代码库:如何重构在Java中关闭流?

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    if (is != null) { 
     try { 
      is.close(); 
     } catch (IOException e) { 
      // handle error 
     } 
    } 
} 

IMO这是非常的fugly,难以阅读,尤其是最后块内的部分(是否真的需要捕获2个IOException异常?)。无论如何简化代码,使其看起来更清洁?

+0

请注意,我不能使用外部库,如Apache IOUtils,除非它经过多个实体的测试和批准 – david 2010-10-22 01:33:35

+5

使用Apache IOUtils的关键在于它已经被无数其他人测试过了。这就是说,我感到你的痛苦。在您的组织内部IOUtils经过测试和认可*一次*是否值得?因此您可以在所有项目中使用它? – 2010-10-22 01:36:27

+0

如果只有这样简单的生活......我必须通过多层次的管理和繁文to节才能让相关工作组看到它。我们仍然坚持使用JDK1.4.2,这是因为已经退役的软件存在'遗留'问题 – david 2010-10-22 01:43:14

回答

1

看到这个question,使用closeQuietly()解决方案。

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    IoUtils.closeQuietly(is); 
} 

// stolen from the cited question above 
public class IoUtils { 

    public static closeQuietly (Closeable closeable) { 
    try { 
     closeable.close(); 
    } catch (IOException logAndContinue) { 
     ... 
    } 
    } 
} 

或等待JDK7's ARM blocks

1

首先,关于使用IOUtils - 可能值得一试,告诉上司他们可能使用的应用程序服务器/ Java运行时环境使用IOUtils以及类似的库本身。所以本质上你不会在你的架构中引入新的组件。

二,不,不是真的。除了编写自己的实用程序来模拟IOUtils的closeQuietly方法之外,没有任何办法可以解决这个问题。现在

+0

嘿,如果closeQuietly是开源,请将其复制到您的项目中。 – 2010-10-22 02:09:36

+0

...而可重复使用和模块化的发明者高兴地在他的坟墓里休息...... – Isaac 2010-10-22 02:28:21

+0

close静静地忽略了异常。这从来不是一个好习惯。此外,大卫想要“处理错误”。 – mschonaker 2010-10-22 05:51:21

1
public class Util { 
    public static void closeStream(inputStream is) { 
     if (is != null) { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       // log something 
     } 
    } 
} 

你的代码是

InputStream is = null; 
try { 
    is = url.openConnection().getInputStream(); 
    // ..... 
} catch (IOException e) { 
    // handle error 
} finally { 
    Util.closeStream(is); 
} 

没有太多事情可做的IOException异常在catch可能有一些特殊的处理。

+0

我喜欢这个,但我会倾向于更进一步,并创建Util.openStream(url),以便调用者不在2个不同的抽象层次上操作。 – 2010-10-22 14:33:03

3

为什么什么东西?这是工作代码。这是正确的。

保留它。

+0

对于反指称,http://www.klocwork.com/blog/2010/10/refactoring-if-it-aint-broken-dont-fix-it/ – andersoj 2010-10-22 10:14:52

+0

他没有问,“我该怎么办“他问,”我该怎么做。“ – 2010-10-22 17:44:04

+0

我在问为什么。为什么应该有一个干扰工作代码的预算?在那工作*生成*代码。我将生成的代码视为目标代码,我不会惹恼它。 – EJP 2010-10-23 00:53:02

0

您可以定义是这样的地方:

private static interface InputStreamCallback { 

    public void doIt(InputStream is) throws IOException; 

} 

private void with(InputStreamCallback cb) { 

    InputStream is = null; 

    // Creational code. Possibly adding an argument 

    try { 
     cb.doIt(is); 
    } catch (IOException e) { 
     // handle error or rethrow. 
     // If rethrow add throws to method spec. 
    } finally { 
     if (is != null) { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       // handle error or rethrow. 
      } 
     } 
    } 
} 

并调用这样的代码:

with(new InputStreamCallback() { 

    @Override 
    public void doIt(InputStream is) throws IOException { 
     is = url.openConnection().getInputStream(); 
     // ..... 
    } 

}); 

如果你在一个辅助类方法static声明,那么你甚至可以做一个它的import static

有一个缺点。您需要声明url final。

编辑:创建代码不是重点。你可以用几种方法来安排它。回调是重点。你可以隔离你在那里需要做什么。