Чи працює остаточний блок, навіть якщо ви кинете новий виняток?


142

У цьому коді буде someVarвстановлено, навіть якщо блок лову виконується і другий виняток буде кинутий?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}

2
Тому що є обставини , при яких поведінка не як і слід було очікувати, як зазначено @GaryF
JAX

1
Варто відзначити, що остаточний блок може не виконуватись так, як очікувалося, якщо він кидає виняток або робить повернення.
Пітер Лоурі

Відповіді:


184

Так, нарешті блоки завжди працюють ... за винятком випадків, коли:

  • Нитка, на якій працює блок try-catch-нарешті, знищується або переривається
  • Ти використовуєш System.exit(0);
  • Основний VM знищується якимось іншим способом
  • Основне обладнання певним чином є непридатним

Крім того, якщо метод у вашому остаточному блоці викидає невловимий виняток, після цього нічого не буде виконано (тобто виняток буде викинуто, як і в будь-якому іншому коді). Дуже поширений випадок, коли це відбувається, є java.sql.Connection.close().

Як осторонь, я здогадуюсь, що використаний вами зразок коду - це лише приклад, але будьте обережні, вкладаючи фактичну логіку все-таки в блок. Остаточно блок призначений для очищення ресурсів (закриття з'єднань з БД, звільнення ручок файлів тощо), а не для логіки обов'язкового запуску. Якщо це потрібно запустити, зробіть це перед блоком спробу-лову, подалі від чогось, що може кинути виняток, оскільки ваш намір майже точно функціонально той самий.


4
Що ви тут маєте на увазі під "потоком, у якому запущений блок try-catch-нарешті, [...] перервано"? Можливо, ця документація сформульована погано, але Thread.interrupt () не призведе до того, що остаточний блок буде пропущений, будь то викинутий з блоку спробу чи блоку. Чи означає це використання "перерване", щоб означати щось більш жорстоке, як Thread.stop ()?
Джо Керні

@Joe: Так, я думаю, що документальне оформлення тут мало сформульоване, і що вони означають загальне переривання в роботі потоку.
GaryF

@GaryF - Я думаю, що ви цитуєте з JLS. Формулювання JLS іноді є дещо дивним, але ви зазвичай виявите, що значення дивної термінології чітко визначено в інших місцях документа. JLS є специфікацією і в якості основної мети має точність (а не читабельність).
Стівен С

1
@Stephen C - насправді, що вийшов з підручника JavaSE (пов’язаного з іншими). Це може бути подібним чином написано в JLS, але я не можу знайти відповідну частину. Я очікував цього в главі 11 (Винятки), главі 14 (Виписки) або главі 15 (Вирази), але я не бачу нічого, що стосується перебоїв прямо. Мені, безумовно, було б цікаво побачити це.
GaryF

1
@GaryF - бачу. Насправді JLS говорить про "нормальне" та "різке" припинення висловлювань, і є розділ (14.1), який визначає термінологію. Потім поведінка finallyконкретизується в умовах нормальних і різких припинень.
Стівен С

10

Так.

Дивіться документацію :

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

Винятки:

Примітка: Якщо JVM закривається під час виконання пробного коду, блок остаточного блоку може не виконатись. Так само, якщо потік, який виконує код спробу вилову, перерваний або знищений, остаточний блок може не виконатись, хоча програма в цілому продовжується.


2

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

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java Спробуйте остаточно заблокувати блокування


2

Нарешті, завжди виконується, незалежно від того, яка ваша справа

  • спробуй лови-нарешті блок
  • кидки

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

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



1

Так. finallyблок виконується завжди, за винятком випадку, який ви викликаєте System.exit (), оскільки він зупиняє Java VM.


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