Java Try Catch Нарешті блокується без Catch


125

Я переглядаю новий код. Програма має спробувати і, нарешті, лише блок. Оскільки блок вилучення виключений, як працює блок "Блокування", якщо він стикається з винятком чи іншим предметом, що піддається переробці? Це просто йде безпосередньо до остаточного блоку?



25
@mP Кожен повинен робити перегляд коду і задавати їм питання - як дізнатися і вдосконалитись.
Карл Притчетт

Відповіді:


130

Якщо будь-який з кодів у блоці спробу може кинути перевірений виняток, він повинен відображатися в пункті кидків підпису методу. Якщо викинуто неперевірене виняток, воно вимкнеться із методу.

Остаточний блок завжди виконується, викинутий виняток чи ні.


11
Перший абзац не обов'язково відповідає дійсності. Спробуйте блоки можна вкласти. Будь-яке вилучене виняток, перевірене чи ні, буде вимкнено з методу.
Енді Томас

4
Спробуйте блоки можна вкласти, але я б не рекомендував це. Я не пишу код таким чином.
duffymo

2
@duffymo: Що означає "вибух з методу"?
Сьогоднізвітували

5
@Anand лише трохи нетехнічна мова для "кидання винятку".
duffymo

2
Не ігнорується; передають ланцюжок методів.
duffymo

93

Невелика примітка про try/ finally: Нарешті завжди виконується, якщо тільки

  • System.exit() це називається.
  • Збій JVM.
  • У try{}блоці не закінчується (наприклад , нескінченний цикл).

4
Про що try{..} catch{ throw ..} finally{..}? Думаю, нарешті не будуть страчені
sbeliakov

10
У такому випадку нарешті все ще буде називатися. Лише початковий виняток втрачено.
Пітер Лорі

Нарешті, також не буде виконано, якщо ви зателефонували до System.exit () раніше.
mmirror

2
@jyw Це я мав на увазі під першим пунктом у списку вище.
Пітер Лорі

Треба сказати, це охоплює всі основи!
Оскар Браво

39

Специфікація мови Java (1) описує спосіб try-catch-finallyвиконання. Відсутність улову еквівалентно відсутності улову, здатного зловити дану Throwable.

  • Якщо виконання блоку спробу завершено різко через кидок значення V, то є вибір:
    • Якщо тип V під час виконання V присвоюється параметру будь-якого пункту запису оператора спробу, тоді
      ……
    • Якщо тип запуску V не присвоюється параметру будь-якого пункту запису оператора спробу, тоді блок остаточно виконується . Тоді є вибір:
      • Якщо блок нарешті завершується нормально, то оператор try закінчується різко через кидання значення V.
      • Якщо остаточний блок різко завершується з причини S, то оператор спробу завершується різко через причину S (і кидання значення V відкидається і забувається).

(1) Виконання спроб улов


16

Внутрішній нарешті виконується до викидання винятку до зовнішнього блоку.

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

Призводить до

A
B
X
Y
Z

6

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

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

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

Між іншим, спроба / нарешті - досить поширена справа для управління ресурсами, оскільки у Java немає руйнівників.

Наприклад -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

«Нарешті», ще одна порада: якщо ви дійсно потрудилися поставити в улові, або зловити конкретний (очікується) Throwable підкласів, або просто зловити «Throwable», НЕ «Виключення», для загального прийому всієї пастки помилок. Занадто багато проблем, таких як рефлексивні рефлекси, викидають "Помилки", а не "Винятки", і вони будуть ковзати під будь-яким кодом "зловити всіх":

catch ( Exception e) ...  // doesn't really catch *all*, eh?

зробіть це замість цього:

catch ( Throwable t) ...

Дивіться відповідь Карлоса Гюбергера нижче щодо негарної частини.
mplwork

3

Версії Java до версії 7 дозволяють використовувати ці три комбінації " пробувати-нарешті" ...

try - catch
try - catch - finally
try - finally

finallyблок завжди буде виконуватися незалежно від того, що відбувається в блоці tryабо / та catch. тому якщо catchблоку немає , виняток тут не оброблятиметься.

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

  • Блок спробу Java повинен супроводжуватися або блокуванням, або нарешті.
  • Для кожного блоку спробу може бути нульове або більше блоків, але лише один.
  • Остаточно блок не буде виконаний, якщо програма завершиться (або зателефонувавши до System.exit (), або викликавши фатальну помилку, яка призведе до переривання процесу).

1
"до того, як версія 7 дозволить" ви маєте на увазі, що Java 7 та Java 8 не дозволяють цих трьох комбінацій? Я сумніваюся, що це ви маєте на увазі, але саме це означає вашу відповідь.
Loduwijk

чи остаточно виконується блок, якщо у блоці спробу є зворотний вираз?
Рахул Ядав

@Rahul Так, нарешті, зателефонують. Ref: stackoverflow.com/questions/65035 / ...
roottraveller

1
@Aaron - новий синтаксис для пробного використання ресурсу, який автоматично викликає .close () на будь-якому, побудованому в межах паронів відразу після ключового слова спробувати.
Робопрог

2

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

Виняток викидається з блоку, як і в будь-якому іншому випадку, коли його не спіймали.

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

Блоки спіймання і, нарешті, є ортогональними частинами блоку спробу. Ви можете мати те або інше. З Java 7 ви не зможете мати жодного!


1

Ви не пробуєте це з цією програмою? Він остаточно блокує та виконує остаточний блок, але виняток не оброблятиметься. Але, цей виняток може бути відмінено в остаточному блоці!


1

Остаточно блок виконується після завершення пробного блоку. Якщо щось кидається всередині блоку спробу, коли він виходить, нарешті блок виконується.


0

Всередині tryблоку ми пишемо коди, які можуть кинути виняток. catchБлок , де ми обробляємо виключення. finallyБлок не завжди виконується незалежно від того , чи відбувається виключення чи ні.

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


0

Незалежно від викиду, викинутого в tryблоці чи не, finallyблок буде виконаний. Виняток не буде спійманий.

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