Um bloco finalmente é executado mesmo se você lançar uma nova exceção?

142

Nesse código será someVardefinido mesmo se o bloco catch for executado e a segunda exceção for lançada?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}
jax
fonte
2
Uma vez que existem casos em que o comportamento não é, como esperado, tal como indicado por @GaryF
JAX
1
Vale ressaltar que o bloco final pode não ser executado conforme o esperado se gerar uma exceção ou retornar.
Peter Peterrey

Respostas:

184

Sim, os blocos finalmente sempre são executados ... exceto quando:

  • O encadeamento executando o bloco try-catch-finalmente é interrompido ou interrompido
  • Você usa System.exit(0);
  • A VM subjacente é destruída de alguma outra maneira
  • O hardware subjacente é inutilizável de alguma forma

Além disso, se um método no seu bloco finalmente lança uma exceção não capturada, nada depois será executado (ou seja, a exceção será lançada como faria em qualquer outro código). Um caso muito comum onde isso acontece é java.sql.Connection.close().

Como um aparte, acho que o exemplo de código que você usou é apenas um exemplo, mas tome cuidado para colocar a lógica real dentro de um bloco final. O bloco final é destinado à limpeza de recursos (fechando conexões com o banco de dados, liberando identificadores de arquivos etc.), não para a lógica de execução obrigatória. Se for necessário executá-lo antes do bloco try-catch, afaste-se de algo que possa gerar uma exceção, pois sua intenção é quase certamente funcionalmente a mesma.

GaryF
fonte
4
O que você quer dizer aqui com "O thread executando o bloco try-catch-finalmente está [...] interrompido"? Talvez essa documentação esteja mal formulada, mas Thread.interrupt () não fará com que o bloco finalmente seja ignorado, seja lançado da tentativa ou do bloco de captura. Esse uso "interrompido" significa algo mais violento, como Thread.stop ()?
Joe Kearney
@ Joe: Sim, acho que a documentação está um pouco mal formulada aqui, e que eles significam uma interrupção geral na atividade do thread.
GaryF
@ GaryF - Eu acho que você está citando o JLS. A redação do JLS às vezes é um pouco estranha, mas você normalmente descobrirá que o significado da terminologia estranha é definido claramente em outras partes do documento. O JLS é uma especificação e tem precisão (em vez de legibilidade) como objetivo principal.
Stephen C
1
@ Stephen C - Na verdade, isso veio do tutorial do JavaSE (vinculado por outros). Pode ter a mesma redação no JLS, mas não consigo encontrar a parte relevante. Eu esperava isso no capítulo 11 (Exceções), no capítulo 14 (Declarações) ou no capítulo 15 (Expressões), mas não consigo ver nada referente a interrupções explicitamente. Eu certamente estaria interessado em ver isso.
GaryF
1
@ GaryF - entendo. Na verdade, o JLS fala sobre o encerramento "normal" e "abrupto" de instruções, e há uma seção (14.1) que define a terminologia. O comportamento de finallyé então especificado em termos de terminações normais e abruptas.
Stephen C
10

Sim.

Veja a documentação :

O bloco finalmente sempre é executado quando o bloco try termina.

Exceções:

Nota: Se a JVM sair enquanto o código try ou catch estiver sendo executado, o bloco finalmente poderá não ser executado. Da mesma forma, se o encadeamento que executa o código try ou catch for interrompido ou eliminado, o bloco finalmente pode não ser executado, mesmo que o aplicativo como um todo continue.

froadie
fonte
2

Finalmente, o bloco sempre é executado.

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 Try Catch Finalmente Bloquear com Throw

Vasanth Umapathy
fonte
2

Finalmente, é sempre executado, não importa qual seja o seu caso.

  • bloco try-catch-finalmente
  • joga

Para exceções não verificadas, o java não exige, tratamento de erros. sendo esse o motivo, se ocorrer uma exceção desmarcada no bloco finalmente e não for feito nenhum tratamento para isso, o código escrito abaixo desse ponto (onde ocorreu o erro) não será executado.

Por isso, sugiro sempre lidar com todas as exceções, sejam marcadas ou desmarcadas. Dessa forma, você pode garantir que o bloco de código finalmente também seja executado, independentemente da ocorrência de exceção não verificada. você tem um lugar na captura de subninho e finalmente bloqueia para fazer o trabalho necessário.

yug
fonte
1

Sim. finallyO bloco é executado sempre, exceto no caso em que você chama System.exit () porque interrompe o Java VM.

Vladimir Ivanov
fonte
Ganchos de desligamento ainda são chamados após System.exit (), mas os segmentos não pertencentes ao sistema são todos parados.
Peter Peterrey