代码之家  ›  专栏  ›  技术社区  ›  hpique

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

  •  5
  • hpique  · 技术社区  · 15 年前

    我经常这样写代码:

    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 回复  |  直到 15 年前
        1
  •  5
  •   Nikita Rybak    15 年前

    我通常把你的内容 finally 阻止一个助手。这样地

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

    Closeable 接口由许多类(输入流、数据库连接等)实现,因此这有点像通用助手。

        2
  •  6
  •   Shervin Asgari    15 年前

    如果不想编写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);
        }
       }
     }
    

    更具可读性,并生成关闭流的正确方法。这与所有 Closeable 界面

        3
  •  4
  •   John Vint    15 年前

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

      public static void closeIO(Closeable closeable){
          if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
        4
  •  3
  •   Faisal Feroz    15 年前

    Java 7正在尝试使用资源支持。检查 this 更多信息。

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

    使用Java 7中的资源语言特性的新尝试,可以有效地将流参数声明为TIVE构造的一部分,编译器生成代码来自动和干净地管理这些资源。

    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();
        }
    }
    
        5
  •  1
  •   Edwin Buck    15 年前

    我倾向于同意其他人提出的方法 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);
    

    除了这个额外的特性,它基本上是其他人提供的解决方案。

        6
  •  1
  •   ILMTitan    15 年前

    我发现通常最好不要尝试捕获,最后都在同一个块中。最好有一个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的需要。

        7
  •  0
  •   Nikita Rybak    15 年前

    用方法写…

    BuffereWriter getMyWriter()
    {
    
    // your code....
    
    return w;
    }
    
        8
  •  0
  •   axtavt    15 年前

    这里可以应用模板方法模式:

    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) { ... }
    });
    
    推荐文章