throws Exception in finally blocks

2019-01-07 04:43发布

Is there an elegant way to handle exceptions that are thrown in finally block?

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?

14条回答
Evening l夕情丶
2楼-- · 2019-01-07 04:58

I typically use one of the closeQuietly methods in org.apache.commons.io.IOUtils:

public static void closeQuietly(OutputStream output) {
    try {
        if (output != null) {
            output.close();
        }
    } catch (IOException ioe) {
        // ignore
    }
}
查看更多
手持菜刀,她持情操
3楼-- · 2019-01-07 05:01

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(); 
    }
  }
}
查看更多
做自己的国王
4楼-- · 2019-01-07 05:02

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).

查看更多
Deceive 欺骗
5楼-- · 2019-01-07 05:04

If you're using Java 7, and resource implements AutoClosable, you can do this (using InputStream as an example):

try (InputStream resource = getInputStream()) {
  // Use the resource.
}
catch( Exception ex ) {
  // Problem with the resource.
}
查看更多
看我几分像从前
6楼-- · 2019-01-07 05:04
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.

查看更多
时光不老,我们不散
7楼-- · 2019-01-07 05:04

Changing Resource from best answer to Closeable

Streams implements Closeable Thus you can reuse the method for all streams

protected void closeQuietly(Closeable resource) {
    if (resource == null) 
        return;
    try {
        resource.close();
    } catch (IOException e) {
        //log the exception
    }
}
查看更多
登录 后发表回答