Java 在 finally 块中抛出异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/481446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
throws Exception in finally blocks
提问by Paul
Is there an elegant way to handle exceptions that are thrown in finally
block?
有没有一种优雅的方法来处理finally
块中抛出的异常?
For example:
例如:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
How do you avoid the try
/catch
in the finally
block?
如何避免在try
/catch
在finally
块?
采纳答案by Darron
I usually do it like this:
我通常这样做:
try {
// Use the resource.
} catch( Exception ex ) {
// Problem with the resource.
} finally {
// Put away the resource.
closeQuietly( resource );
}
Elsewhere:
别处:
protected void closeQuietly( Resource resource ) {
try {
if (resource != null) {
resource.close();
}
} catch( Exception ex ) {
log( "Exception during Resource.close()", ex );
}
}
回答by Pierre
One solution, if the two Exceptions are two different classes
一种解决方案,如果两个异常是两个不同的类
try {
...
}
catch(package1.Exception err)
{
...
}
catch(package2.Exception err)
{
...
}
finally
{
}
But sometimes you cannot avoid this second try-catch. e.g. for closing a stream
但有时您无法避免第二次尝试捕获。例如用于关闭流
InputStream in=null;
try
{
in= new FileInputStream("File.txt");
(..)// do something that might throw an exception during the analysis of the file, e.g. a SQL error
}
catch(SQLException err)
{
//handle exception
}
finally
{
//at the end, we close the file
if(in!=null) try { in.close();} catch(IOException err) { /* ignore */ }
}
回答by Ken Henderson
If you can you should test to avoid the error condition to begin with.
如果可以,您应该先进行测试以避免出现错误情况。
try{...}
catch(NullArgumentException nae){...}
finally
{
//or if resource had some useful function that tells you its open use that
if (resource != null)
{
resource.Close();
resource = null;//just to be explicit about it was closed
}
}
Also you should probably only be catching exceptions that you can recover from, if you can't recover then let it propagate to the top level of your program. If you can't test for an error condition that you will have to surround your code with a try catch block like you already have done (although I would recommend still catching specific, expected errors).
此外,您可能应该只捕获可以从中恢复的异常,如果无法恢复,则让它传播到程序的顶层。如果您无法测试错误情况,您将不得不像您已经完成的那样用 try catch 块包围您的代码(尽管我仍然建议您仍然捕获特定的、预期的错误)。
回答by Eduard Wirch
Why do you want to avoid the additional block? Since the finally block contains "normal" operations which may throw an exception AND you want the finally block to run completely you HAVE to catch exceptions.
为什么要避免附加块?由于 finally 块包含可能引发异常的“正常”操作,并且您希望 finally 块完全运行,因此您必须捕获异常。
If you don't expect the finally block to throw an exception and you don't know how to handle the exception anyway (you would just dump stack trace) let the exception bubble up the call stack (remove the try-catch from the finally block).
如果您不希望 finally 块抛出异常,并且无论如何也不知道如何处理异常(您只需转储堆栈跟踪),让异常冒泡到调用堆栈中(从 finally 中删除 try-catch堵塞)。
If you want to reduce typing you could implement a "global" outer try-catch block, which will catch all exceptions thrown in finally blocks:
如果你想减少输入,你可以实现一个“全局”外部 try-catch 块,它将捕获 finally 块中抛出的所有异常:
try {
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
} catch (Exception ex) {
...
}
回答by Sam Saffron
You could refactor this into another method ...
您可以将其重构为另一种方法......
public void RealDoSuff()
{
try
{ DoStuff(); }
catch
{ // resource.close failed or something really weird is going on
// like an OutOfMemoryException
}
}
private void DoStuff()
{
try
{}
catch
{
}
finally
{
if (resource != null)
{
resource.close();
}
}
}
回答by OscarRyz
I usually do this:
我通常这样做:
MyResource r = null;
try {
// use resource
} finally {
if( r != null ) try {
r.close();
} catch( ThatSpecificExceptionOnClose teoc ){}
}
Rationale: If I'm done with the resource and the only problem I have is closing it, there is not much I can do about it. It doesn't make sense either to kill the whole thread if I'm done with the resource anyway.
理由:如果我已经完成了资源的使用,而我唯一的问题就是关闭它,那么我无能为力。如果我已经完成了资源,那么杀死整个线程也是没有意义的。
This is one of the cases when at least for me, it is safe to ignore that checked exception.
至少对我来说,这是一种情况,可以安全地忽略该检查异常。
To this day I haven't had any problem using this idiom.
直到今天,我在使用这个习语时还没有遇到任何问题。
回答by CJS
I typically use one of the closeQuietly
methods in org.apache.commons.io.IOUtils
:
我通常使用以下closeQuietly
方法之一org.apache.commons.io.IOUtils
:
public static void closeQuietly(OutputStream output) {
try {
if (output != null) {
output.close();
}
} catch (IOException ioe) {
// ignore
}
}
回答by Tom Hawtin - tackline
try {
final Resource resource = acquire();
try {
use(resource);
} finally {
resource.release();
}
} catch (ResourceException exx) {
... sensible code ...
}
Job done. No null tests. Single catch, include acquire and release exceptions. Of course you can use the Execute Around idiom and only have to write it once for each resource type.
任务完成。没有空测试。单个捕获,包括获取和释放异常。当然,您可以使用 Execute Around 习惯用法,并且只需为每种资源类型编写一次。
回答by MB.
Arguably a bit over the top, but maybe useful if you're letting exceptions bubble up and you can't log anything from within your method (e.g. because it's a library and you'd rather let the calling code handle exceptions and logging):
可以说有点过头了,但如果你让异常冒泡并且你不能从你的方法中记录任何东西(例如,因为它是一个库,你宁愿让调用代码处理异常和日志记录),这可能很有用:
Resource resource = null;
boolean isSuccess = false;
try {
resource = Resource.create();
resource.use();
// Following line will only run if nothing above threw an exception.
isSuccess = true;
} finally {
if (resource != null) {
if (isSuccess) {
// let close throw the exception so it isn't swallowed.
resource.close();
} else {
try {
resource.close();
} catch (ResourceException ignore) {
// Just swallow this one because you don't want it
// to replace the one that came first (thrown above).
}
}
}
}
UPDATE: I looked into this a bit more and found a great blog post from someone who has clearly thought about this more than me: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.htmlHe goes one step further and combines the two exceptions into one, which I could see being useful in some cases.
更新:我对此进行了更多研究,并从比我更清楚地考虑过这个问题的人那里找到了一篇很棒的博客文章:http: //illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html他更进一步,将两个异常合二为一,我认为这在某些情况下很有用。
回答by Grogi
After lots of consideration, I find the following code best:
经过多次考虑,我发现以下代码最好:
MyResource resource = null;
try {
resource = new MyResource();
resource.doSomethingFancy();
resource.close();
resource = null;
} finally {
closeQuietly(resource)
}
void closeQuietly(MyResource a) {
if (a!=null)
try {
a.close();
} catch (Exception e) {
//ignore
}
}
That code guarantees following:
该代码保证以下内容:
- The resource is freed when the code finished
- Exceptions thrown when closing the resource are not consumed without processing them.
- The code does not try to close the resource twice, no unnecessary exception will be created.
- 代码完成后资源被释放
- 关闭资源时抛出的异常不会在不处理它们的情况下被消耗。
- 代码不会尝试关闭资源两次,不会创建不必要的异常。