Різниця між спробою-нарешті та спробою-зловити


90

Яка різниця між

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

і

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

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

Крім того, чи є спосіб отримати доступ до винятку із пропозиції "останнє"?

Відповіді:


121

Це дві різні речі:

  • Блок catch виконується лише в тому випадку, якщо в блоці try вилучено виняток.
  • Блок нарешті виконується завжди після блоку 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 у своєму коментарі, немає можливості отримати доступ до винятку всередині блоку нарешті, оскільки блок нарешті виконується, навіть якщо винятку немає.

Звичайно, ви можете оголосити змінну, яка містить виняток поза вашим блоком, і призначити значення всередині блоку catch. Згодом ви можете отримати доступ до цієї змінної всередині вашого блоку нарешті.

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.
  • Нарешті, він завжди буде виконаний після блоків 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. один нарешті блок, або
  2. один або кілька блоків лову, або
  3. один або кілька блоків лову і один нарешті блок

Отже, наступний код також буде дійсним:

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
}

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, або кінцеве
  2. Він може мати кілька пропозицій catch, але лише одне остаточне
  3. Під час будь-якого виконання, якщо виникають помилки, елемент керування переноситься у відповідний блок Catch і виконує оператори, а блок нарешті виконується.

Немає значення, що завжди виконується блок нарешті, отже, загалом використовується блок нарешті, коли у вас є сеанси, підключення до бази даних або відкриті файли чи сокети, тоді буде розміщено код для закриття цих підключень. Це лише для того, щоб переконатися, що в додатку не виникає витоків пам’яті або не повинно виникати будь-яких інших проблем.


3

Нарешті, блоки блокування досить різні:

У блоці catch ви можете відповісти на викинутий виняток. Цей блок виконується, лише якщо існує необроблена виняток і тип відповідає одному або є підкласом того, що вказаний у параметрі блоку catch. Нарешті, він завжди буде виконаний після блоків try and catch, незалежно від того, є виняток чи ні.


2

У моєму дослідженні Блок нарешті завжди виконується, і він в основному "використовується для закриття будь-яких відкритих з'єднань" і для знищення того, що працює без потреби.


2

Як правило, коли ми використовуємо будь-які ресурси, такі як потоки, підключення тощо., Ми повинні чітко їх закрити, використовуючи нарешті блок. У наведеній нижче програмі ми зчитуємо дані з файлу за допомогою FileReader і закриваємо їх, використовуючи нарешті блок.

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

Нарешті, блок завжди виконується. Блок лову виконується лише тоді, коли вловлюється виняток, який відповідає параметру блоки.


1

Навіть у першій формі ви можете записати це за допомогою методу виклику. Отже, великої переваги немає, якщо ви не хочете зробити там спеціальну обробку.


0

Блок try буде містити заяви, які збираються викликати виняток. Блок catch буде містити посилання, викинуте з блоку try, а необхідні повідомлення генеруються з блоку catch. Нарешті, блок також використовується для закриття використовуваних ресурсів, таких як закриття io, закриття файлів, закриття дБ .. У Java-9 з'явився розширений ресурс try-with, де ресурси оголошені за межами try ..in Enchanced try with resource the catch block є обов’язковим

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.