Чи є сенс робити "пробувати" нарешті без "лову"?


127

Я побачив такий код:

    try
    {
        db.store(mydata);
    }
    finally
    {
        db.cleanup();
    }

Я думав try, має бути catch?

Чому цей код робить це так?


1
це забезпечує очищення, як згадували інші відповіді, особливо для файлових ручок fopenабо підключення до БД (також на PHP)
MediaVince

Відповіді:


182

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

public void yourOtherMethod() {
    try {
        yourMethod();
    } catch (YourException ex) {
        // handle exception
    }
}    

public void yourMethod() throws YourException {
    try {
        db.store(mydata);
    } finally {
        db.cleanup();
    }
}

17
зазвичай використовується із замками, як у: lock.lock (); спробуйте {/ * locked * /} нарешті {lock.unlock ()}
хвилини

Що станеться, якщо виняток кинемо всередину?
Barth

1
@barth Коли немає catchблоку, викинутий виняток finallyбуде виконуватися перед будь-яким винятком у tryблоці. Отже, якщо є два винятки: один tryі один, finallyєдиний виняток, який буде кинутий, - це "в" finally. Така поведінка не однакова у PHP та Python, оскільки обидва винятки будуть перекинуті одночасно на цих мовах, і порядок винятків - це tryспочатку finally.
Дощ

72

Це там, тому що програміст хотів переконатися, що db.cleanup()його викликають, навіть якщо код всередині блоку спробу видає виняток. Будь-які винятки не будуть оброблятися цим блоком, але вони будуть поширюватися вгору лише після того, як остаточно буде виконаний блок.


23
+1 Рівно. tryТільки там , щоб дозволити finally. Винятки не спіймані.
zockman

2
+1 для пояснення, що виняток продовжує зберігати стек, поки його не застане. Спасибі
Code Jockey

20

Чому цей код робить це так?

Тому що, мабуть, код не знає, як обробляти винятки на цьому рівні. Це добре - до тих пір, поки це робить один із абонентів, тобто поки виняток десь обробляється десь.

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

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


2

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

Це також часто використовується для запобігання занадто великого гніздування:

try
{
    if (foo) return false;
    //bla ...
    return true;
}
finally
{
    //clean up
}

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


0

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


0

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

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

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