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;
    }
}

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.


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.


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


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.



1

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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.