2010-10-11 62 views
5

我倾向于写代码如下所示的很多:如何简化/重用这个异常处理代码

BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
try { 
    w = new BufferedWriter(new FileWriter(file)); 
    // Do something with w 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    if (w != null) { 
     try { 
      w.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

,通常需要抛出异常,需要关闭,对象和关闭它也可能抛出异常。

我想知道上面的代码是否可以简化或以任何方式重用。

+0

我学习了很多的Java感谢这个问题。 :D – hpique 2010-10-11 20:11:22

回答

5

我通常会将finally块的内容放入帮助程序中。像这样

void close(Closeable c) { 
    if (c != null) { 
     try { 
      c.close(); 
     } catch (IOException e) { 
      // perform logging or just ignore error 
     } 
    } 
} 

Closeable接口由许多类(输入流,数据库连接等)来实现,所以这是有点通用的帮手。

+0

哦!像Closeable这样的东西正是我所期待的。 – hpique 2010-10-11 14:53:24

0

写它的方法...

BuffereWriter getMyWriter() 
{ 

// your code.... 

return w; 
} 
4

是,由于Java 1.5有一个可关闭的接口。您可以有一个关闭任何可关闭类型的静态方法。

public static void closeIO(Closeable closeable){ 
     if (closeable != null) { 
     try { 
      closeable.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

或重复使用来自番石榴的'Closeables'。 – whiskeysierra 2010-10-11 15:31:21

0

模板方法图案这里可以应用:

public class FileTemplate { 
    public void write(File file, WriteCallback c) { 
     BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
     try { 
      w = new BufferedWriter(new FileWriter(file)); 
      c.writeFile(w); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (w != null) { 
       try { 
        w.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

public interface WriteCallback { 
    public void writeFile(BufferedWriter w) throws IOException; 
} 

new FileTemplate().write(file, new WriteCallback() { 
    public void writeFile(BufferedWriter w) { ... } 
}); 
1

我倾向于与其他人谁提供服用Closeable的方法达成一致,但由于maintining很长住计划,我用的解决方案略有不同。基本上它需要一个OutputStream来提供灵活性。

public class IOHandler { 

    private IOHandler(); 

    public static void close(OutputStream out, Closeable c) { 
    if (c != null) { 
     try { 
     c.close(); 
    } catch (IOException e) { 
     out.print(c.printStackTrace().getBytes()); 
    } 
    } 

} 

这样做的主要好处是,你可以把它在多种方式,不再需要专门的工具来处理日志记录异常到stderr,stdout和文件。

IOHandler.close(System.out, openFile); 
IOHandler.close(System.err, openFile); 
IOHandler.close(logFile, openFile); 

除了这一个增加的功能,它基本上是其他人提供的相同的解决方案。

3

Java 7正在尝试资源支持。查看this了解更多信息。

我引用了相关的文字和代码示例这里:

在Java 7中的新的尝试,与资源的语言功能,有效申报的流参数作为尝试,构造的一部分,和编译器会生成代码,为您自动管理这些资源。

private static void customBufferStreamCopy(File source, File target) { 
    try (InputStream fis = new FileInputStream(source); 
     OutputStream fos = new FileOutputStream(target)){ 

     byte[] buf = new byte[8192]; 

     int i; 
     while ((i = fis.read(buf)) != -1) { 
      fos.write(buf, 0, i); 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

+1更多分享在JDK 7 – 2010-10-11 15:07:08

+1

确定的最新变化,但也许他并不想等到2011年中期使用JDK 1.7,不是吗? – romaintaz 2010-10-11 15:38:29

+0

我相信任何客户都会明白。 :P – hpique 2010-10-11 16:11:34

1

我发现通常最好不要尝试捕捉并最终全部在同一个块中。有一个try-catch块和一个单独的try-finally块通常会更好。

try { 
    BufferedWriter w = new BufferedWriter(new FileWriter(file)); // Or any other object that throws exceptions and needs to be closed 
    try { 
     // Do something with w 
    } finally { 
     w.close(); 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

这也避免了任何需要空检查W上。

+0

当基础流仍被创建时,您会遇到问题,但外部流会在构造函数中引发异常。然后底层流不会关闭。 – 2011-08-22 15:41:05

+0

@致命'新的BufferedWriter(作家)'不会抛出任何检查的异常。即使做了,在调用'新的BufferedWriter存在问题(新的FileWriter(文件))'由问题描述,而不是处理异常此方法。为了缓解,你必须将'New FileWriter'分配给一个单独的变量并关闭它。 – ILMTitan 2011-08-22 18:16:24

+0

你对BufferedWriter是正确的,但是这里的主题更一般,你的建议也是非常一般的。由于'close()'契约,您不必分配和关闭FileWriter。 hgpc在他的开场白中做得很对。就像我知道的Apache Commons所有常见库一样 - 而不是偶然。所以接受的答案是最好的 - 它只是改善了正确的做法并减少了样板。这里没什么我会推荐的,即使它在这里可能适用于这种特殊情况。 – 2011-08-22 18:48:52

6

如果你不想写代码在finally块关闭,你应该看看Project Lombok

而不是写正常

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    InputStream in = new FileInputStream(args[0]); 
    try { 
    OutputStream out = new FileOutputStream(args[1]); 
    try { 
     byte[] b = new byte[10000]; 
     while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
     } 
    } finally { 
     out.close(); 
     } 
    } finally { 
    in.close(); 
    } 
    } 
} 

随着龙目岛,你可以写

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 

更可读,和它产生关闭流的正确的方法。这适用于所有的Closeable接口

+2

+1引入lambok(我) – chedine 2010-10-11 18:38:03

+0

龙目岛非常适合样板代码 – 2010-10-12 17:35:27