бросает Exception в наконец-то блоки - PullRequest
98 голосов
/ 27 января 2009

Есть ли элегантный способ обработки исключений, которые выбрасываются в блок finally?

Например:

try {
  // Use the resource.
}
catch( Exception ex ) {
  // Problem with the resource.
}
finally {
   try{
     resource.close();
   }
   catch( Exception ex ) {
     // Could not close the resource?
   }
}

Как избежать использования try / catch в блоке finally?

Ответы [ 14 ]

0 голосов
/ 27 января 2009
try {
    final Resource resource = acquire();
    try {
        use(resource);
    } finally {
        resource.release();
    }
} catch (ResourceException exx) {
    ... sensible code ...
}

Работа выполнена. Нет нулевых тестов. Одиночный улов, включая исключения по приобретению и выпуску. Конечно, вы можете использовать идиому Execute Around и написать его только один раз для каждого типа ресурса.

0 голосов
/ 27 января 2009

Я обычно делаю это:

MyResource r = null;
try { 
   // use resource
} finally {   
    if( r != null ) try { 
        r.close(); 
    } catch( ThatSpecificExceptionOnClose teoc ){}
}

Обоснование: если я закончил работу с ресурсом, и единственная проблема, которая у меня возникла, - это закрытие, я мало что могу с этим сделать. В любом случае, нет смысла уничтожать весь поток, если я покончу с ресурсом.

Это один из случаев, когда, по крайней мере для меня, можно игнорировать это проверенное исключение.

До сих пор у меня не было проблем с использованием этой идиомы.

0 голосов
/ 27 января 2009

Вы можете изменить это в другой метод ...

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(); 
    }
  }
}
0 голосов
/ 27 января 2009

Если вы можете, вы должны проверить, чтобы избежать условия ошибки для начала.

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

Кроме того, вам, вероятно, следует отлавливать только те исключения, из которых вы можете восстановить, если вы не можете восстановить, тогда пусть это распространяется на верхний уровень вашей программы. Если вы не можете проверить наличие ошибки, вам придется окружить свой код блоком try catch, как вы уже сделали (хотя я бы по-прежнему рекомендовал перехватывать определенные, ожидаемые ошибки).

...