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

发布于 2024-09-26 15:25:16 字数 500 浏览 1 评论 0原文

我经常写这样的代码:

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

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

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

I tend to write code like the following a lot:

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

It usually involves an object that throws exceptions and needs to be closed, and that closing it may also throw an exception.

I was wondering if the above code can be simplified or reused in any way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

爱你是孤单的心事 2024-10-03 15:25:16

如果您不想在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 接口

If you don't want to write code for closing in finally block, you should have a look at Project Lombok

Instead of writing the normal

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

With Lombok you can write

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

Much more readable, and it generates the correct way of closing the Stream. This works with all the Closeable interfaces

热风软妹 2024-10-03 15:25:16

我通常将 finally 块的内容放在助手中。就像这个

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

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

I usually put contents of your finally block in a helper. Like this

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

Closeable interface is implemented by many classes (input streams, database connections, etc), so this is kinda general-purpose helper.

瀞厅☆埖开 2024-10-03 15:25:16

是的,从java 1.5开始就有一个Closeable接口。您可以使用静态方法来关闭任何 Closeable 类型。

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

Yes, since java 1.5 there is a Closeable interface. You can have a static method that closes any Closeable type.

  public static void closeIO(Closeable closeable){
      if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
独留℉清风醉 2024-10-03 15:25:16

Java 7正在尝试资源支持。检查这个更多信息。

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

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

Java 7 is having try with resource support. Check this out for more information.

I am quoting the relevant text and a code example here:

with the new try-with-resource language feature in Java 7, you effectively declare your stream arguments as part of the try-construct, and the compiler generates code that manages those resources automatically and cleanly for you.

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();
    }
}
屋顶上的小猫咪 2024-10-03 15:25:16

我倾向于同意其他人提供的采用 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);

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

I tend to agree with others who offer a method taking a Closeable, but due to maintining very long lived programs, the solution I use is slightly different. Basically it takes an OutputStream to provide flexibility.

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

}

The main advantages of this is that you can call it in a variety of ways, removing the need for specialized utilities to handle logging exceptions to stderr, stdout, and files.

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

Other than this one added feature, it's basically the same solution others have offered.

怂人 2024-10-03 15:25:16

我发现通常最好不要将 try catch 和 finally 全部放在同一个块中。通常最好有一个 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 进行空检查的需要。

I find it is usually best not to have try catch and finally all in the same block. It is often better to have a try-catch block and a separate try-finally block.

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

This also avoids any need to null check w.

醉酒的小男人 2024-10-03 15:25:16

将其写在方法中...

BuffereWriter getMyWriter()
{

// your code....

return w;
}

Write it in a method ...

BuffereWriter getMyWriter()
{

// your code....

return w;
}
指尖微凉心微凉 2024-10-03 15:25:16

可以在此处应用模板方法模式:

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

A template method pattern can be applied here:

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) { ... }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文