如何简化/重用此异常处理代码

时间:2010-10-11 14:47:23

标签: java exception exception-handling code-reuse

我倾向于编写如下代码:

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();
        }
    }
}

它通常涉及一个抛出异常并需要关闭的对象,关闭它也可能会引发异常。

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

8 个答案:

答案 0 :(得分: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();
    }
  }
}

使用Lombok,你可以写

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);
    }
   }
 }

更具可读性,它可以生成关闭Stream的正确方法。这适用于所有Closeable接口

答案 1 :(得分:5)

我通常会将finally块的内容放在帮助器中。喜欢这个

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

Closeable接口由许多类(输入流,数据库连接等)实现,因此这是一种通用的帮助器。

答案 2 :(得分:4)

是的,因为java 1.5有一个Closeable接口。您可以使用静态方法关闭任何Closeable类型。

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

答案 3 :(得分:3)

Java 7正在尝试使用资源支持。请查看this以获取更多信息。

我在这里引用相关文本和代码示例:

使用Java 7中新的try-with-resource语言功能,您可以有效地将流参数声明为try-construct的一部分,并且编译器会生成自动且干净地管理这些资源的代码。

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();
    }
}

答案 4 :(得分:1)

我倾向于同意提供Closeable方法的其他人,但由于维护了很长时间的程序,我使用的解决方案略有不同。基本上,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);

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

答案 5 :(得分: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。

答案 6 :(得分:0)

将其写入方法......

BuffereWriter getMyWriter()
{

// your code....

return w;
}

答案 7 :(得分: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) { ... }
});