Имеет ли смысл делать "try-finally" без "catch"?

Я видел такой код:

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

Я думал, что try должен иметь catch?

Почему этот код делает это таким образом?

Ответ 1

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

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

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

Ответ 2

Это там, потому что программист хотел удостовериться, что вызов db.cleanup() вызывается, даже если код внутри блока try выдает исключение. Любые исключения не будут обрабатываться этим блоком, но они будут распространяться только вверх после выполнения блока finally.

Ответ 3

Почему этот код делает это таким образом?

Потому что, очевидно, код не знает, как обрабатывать исключения на этом уровне. Thats fine - пока один из вызывающих абонентов делает это, то есть до тех пор, пока исключение в конечном итоге будет обрабатываться.

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

Но код все еще нуждается в очистке своих ресурсов (потому что, если он не будет, они будут течь), поэтому он делает это только в предложении finally, убедившись, что это всегда происходит, независимо от того, было ли исключено исключение.

Ответ 4

Блок finally гарантирует, что даже при вызове RuntimeException (возможно, из-за некоторой ошибки в вызываемом коде) будет выполнен вызов db.cleanup().

Это также часто используется для предотвращения слишком большого вложенности:

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

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

Ответ 5

Код делает это, чтобы гарантировать, что база данных будет закрыта.
Обычно, как вы делаете это, нужно поместить всю вашу базу данных, обращаясь к коду в блоке try, а затем поместить вызов для закрытия базы данных в блоке finally.
Попытка... наконец-то работает, означает, что код в блоке try запущен, а код в блоке finally запускается, когда это заканчивается... несмотря ни на что.
За исключением компьютера, который дергается со стены, окончательно выполнится.
Это означает, что даже если вызывается исключение, и для выполнения этого метода требуется три года, он все равно останется в блоке finally и база данных будет закрыта.