Разница между try-finally и try-catch

91

В чем разница между

try {
    fooBar();
} finally {
    barFoo();
}

а также

try {
  fooBar();
} catch(Throwable throwable) {
    barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

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

Кроме того, есть ли способ получить доступ к исключению из предложения finally?

Виджай Котари
источник

Ответы:

121

Это две разные вещи:

  • Блок catch выполняется только в том случае, если в блоке try выбрасывается исключение.
  • Блок finally выполняется всегда после блока try (-catch), независимо от того, возникло ли исключение.

В вашем примере вы не показали третью возможную конструкцию:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

И, как @codeca говорит в своем комментарии, нет возможности получить доступ к исключению внутри блока finally, потому что блок finally выполняется, даже если нет исключения.

Конечно, вы можете объявить переменную, которая содержит исключение вне вашего блока, и присвоить значение внутри блока catch. Впоследствии вы можете получить доступ к этой переменной внутри вашего блока finally.

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}
тангенс
источник
11
Следствием тому является то , что вы не можете получить доступ к Throwableиз finallyблока, потому что не может бытьThrowable .
Дин Хардинг
11

Это не вариации, это принципиально разные вещи. finallyвыполняется всегда , catchтолько когда возникает исключение.

Мишель Буддинг
источник
7

Наконец и блоки catch совершенно разные:

  • В блоке catch вы можете ответить на возникшее исключение. Этот блок выполняется только в том случае, если есть необработанное исключение и тип соответствует одному или является подклассом того, который указан в параметре блока catch.
  • Наконец, всегда будет выполняться после блоков try и catch, независимо от того, возникло ли исключение или нет.

Так

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

отличается от

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

значительно.

Если вы определяете блок попытки, вы должны определить

  1. один блок finally, или
  2. один или несколько блоков catch, или
  3. один или несколько блоков catch и один блок finally

Таким образом, следующий код тоже будет действительным:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}
TheMorph
источник
4

try используется для запуска метода, который может вызвать исключение

catch используется, чтобы "поймать" остановить это исключение

finally используется для любой очистки, необходимой для того, чтобы исключение было поймано или нет

try{
    myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
    myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
    myObject = null; // clean up needed from that exception being caught
}
Киран
источник
3
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. Все операторы try должны включать либо одно предложение catch, либо предложение finally.
  2. Он может иметь несколько предложений catch, но только одно предложение finally.
  3. Во время любого выполнения, если возникают какие-либо ошибки, тогда Control передается соответствующему блоку Catch и выполняет операторы, а блок finally выполняется.

Неважно, что блок finally выполняется всегда, так что в целом блок finally используется, когда у вас есть сеансы, соединения с базой данных или файлы или сокеты, тогда будет размещен код для закрытия этих соединений. Это просто для того, чтобы в приложении не было утечек памяти или каких-либо других проблем.

gmhk
источник
3

Наконец и блоки catch совершенно разные:

В блоке catch вы можете ответить на возникшее исключение. Этот блок выполняется только в том случае, если есть необработанное исключение и тип соответствует одному или является подклассом того, который указан в параметре блока catch. Наконец, всегда будет выполняться после блоков try и catch, независимо от того, возникло ли исключение.

Учебник по Android
источник
2

В моем исследовании блок finally всегда выполняется и в основном «используется для закрытия любых открытых соединений» и уничтожения того, что работает без необходимости.

Хари Кришна
источник
2

Обычно, когда мы используем какие-либо ресурсы, такие как потоки, соединения и т. Д., Мы должны закрывать их явно с помощью блока finally. В приведенной ниже программе мы читаем данные из файла с помощью FileReader и закрываем его с помощью блока finally.

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

Может быть, другие ребята вроде меня искали что-то подобное.

Информация с этой страницы tutpoint


источник
1

Блок finally всегда выполняется. Блок Catch выполняется только тогда, когда обнаружено исключение, соответствующее параметру блоков.

мкорпела
источник
1

Даже в первой форме вы можете зарегистрировать его в вызывающем методе. Таким образом, нет большого преимущества, если вы не хотите прямо сейчас заниматься чем-то особенным.

fastcodejava
источник
0

Блок try будет содержать операторы, которые будут вызывать исключение. Блок catch будет содержать ссылку, созданную из блока try, а необходимые сообщения генерируются из блока catch. Блок finally также используется для закрытия используемых ресурсов, таких как закрытие io, закрытие файла, закрытие дБ. В Java -9 появился расширенный ресурс try-with, когда ресурсы объявлены вне try..in enchanced try with resource блок catch является обязательным

Шриниджа
источник