Blocos Java Try Catch Finalmente sem Catch


125

Estou revendo um novo código. O programa tem apenas uma tentativa e, finalmente, um bloco. Como o bloco catch é excluído, como o bloco try funciona se encontrar uma exceção ou algo que possa ser jogado? Apenas vai diretamente para o bloco final?



25
@mP Todos devem fazer revisões de código e fazer perguntas com eles é como aprender e melhorar.
19611 Carl Pritchett

Respostas:


130

Se algum código no bloco try puder gerar uma exceção verificada, ele deverá aparecer na cláusula throws da assinatura do método. Se uma exceção não verificada for lançada, ela será excluída do método.

O bloco final é sempre executado, independentemente de uma exceção ser lançada ou não.


11
O primeiro parágrafo não é necessariamente verdadeiro. Os blocos de tentativa podem ser aninhados. Qualquer exceção não capturada, desmarcada ou não, sairá do método.
Andy Thomas

4
Os blocos de tentativa podem ser aninhados, mas eu não recomendo. Eu não escrevo código dessa maneira.
duffymo

2
@duffymo: Qual é o significado de "borbulhado fora do método"?
todayilearned

5
@ E apenas uma linguagem um pouco não técnica para "lançar uma exceção".
Duffymo 17/07/2015

2
Não é ignorado; passar a cadeia de métodos.
Duffymo 6/11

93

Uma pequena nota em try/ finally: O finalmente sempre será executado, a menos que

  • System.exit() é chamado.
  • A JVM trava.
  • O try{}bloco nunca termina (por exemplo, loop sem fim).

4
Que tal try{..} catch{ throw ..} finally{..}? Eu acho que finalmente não será executado
sbeliakov

10
Nesse caso, finalmente ainda será chamado. Somente a exceção original é perdida.
Peter Lawrey

Finalmente, também não será executado se você chamar System.exit () antes.
mmirror

2
@ jyw Isso é o que eu quis dizer com o primeiro item da lista acima.
Peter Lawrey

Eu tenho que dizer, isso cobre todas as bases!
Oscar Bravo #

39

A especificação da linguagem Java (1) descreve como try-catch-finallyé executada. Não ter captura é equivalente a não ter uma captura capaz de pegar o Throwable fornecido.

  • Se a execução do bloco try for concluída abruptamente devido a um lançamento de um valor V, haverá uma opção:
    • Se o tipo de tempo de execução de V for atribuível ao parâmetro de qualquer cláusula catch da instrução try, então
      ……
    • Se o tipo de tempo de execução de V não for atribuível ao parâmetro de qualquer cláusula catch da instrução try, o bloco final será executado . Depois, há uma escolha:
      • Se o bloco finalmente for concluído normalmente, a instrução try será concluída abruptamente devido a um lançamento do valor V.
      • Se o bloco final for concluído abruptamente pelo motivo S, a instrução try será concluída abruptamente pelo motivo S (e o lançamento do valor V será descartado e esquecido).

(1) Execução do try-catch-finalmente


16

O interior finalmente é executado antes de lançar a exceção no bloco externo.

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

Resulta em

A
B
X
Y
Z

6

O bloco final é sempre executado após o término do bloco try, se a tentativa termina normalmente ou de forma anormal devido a uma exceção, er, lançável.

Se uma exceção é lançada por qualquer código dentro do bloco try, o método atual simplesmente lança novamente (ou continua a lançar) a mesma exceção (depois de executar o bloco finally).

Se o bloco final lança uma exceção / erro / lança, e já existe um lançamento pendente, fica feio. Francamente, esqueço exatamente o que acontece (tanto pela minha certificação anos atrás). Acho que os dois lançadores ficam interligados, mas há um vodu especial que você precisa fazer (ou seja, - uma chamada de método que eu precisaria procurar) para obter o problema original antes que o "finalmente" vomite, er, vomite.

Aliás, try / finalmente é uma coisa bastante comum a ser feita no gerenciamento de recursos, pois o java não possui destruidores.

Por exemplo -

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

"Finalmente", mais uma dica: se você não se preocupam em colocar em um prendedor, ou captura específica (esperado) subclasses throwable, ou apenas pegar "Throwable", não "Exception", para um catch-all interceptação de erro geral. Muitos problemas, como as reflexões, geram "Erros", em vez de "Exceções", e esses erros serão corrigidos por qualquer "pegar tudo" codificado como:

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

faça isso:

catch ( Throwable t) ...

Veja a resposta de Carlos Heuberger abaixo para a parte feia.
mplwork

3

As versões Java anteriores à versão 7 permitem essas três combinações de try-catch-finalmente ...

try - catch
try - catch - finally
try - finally

finally O bloco será sempre executado independentemente do que estiver acontecendo no trycatch bloco ou / e . portanto, se não houver catchbloqueio, a exceção não será tratada aqui.

No entanto, você ainda precisará de um manipulador de exceções em algum lugar do seu código - a menos que queira que seu aplicativo trave completamente, é claro. Depende da arquitetura do seu aplicativo exatamente onde está o manipulador.

  • O bloco try de Java deve ser seguido pelo bloco catch ou finalmente.
  • Para cada bloco try, pode haver zero ou mais blocos catch, mas apenas um bloco finalmente.
  • O bloco final não será executado se o programa sair (chamando System.exit () ou causando um erro fatal que causa a interrupção do processo).

1
"antes da versão 7 permitir" você está sugerindo que o Java 7 e o Java 8 não permitem essas três combinações? Duvido que seja isso que você quer dizer, mas é isso que sua resposta implica.
Loduwijk 22/03

o bloco final é executado se houver uma declaração de retorno no bloco try?
Rahul Yadav

@Rahul Sim, finalmente será chamado. Ref: stackoverflow.com/questions/65035/...
roottraveller

1
@Aaron - nova sintaxe para try-with-resource que chama automaticamente .close () em qualquer coisa construída dentro de parens logo após a palavra-chave try.
Roboprog

2

como o bloco try funciona se encontrar uma exceção ou algo que possa ser jogado

A exceção é lançada para fora do bloco, como em qualquer outro caso em que não é capturada.

O bloco final é executado independentemente de como o bloco try foi encerrado - independentemente de haver alguma captura, independentemente de haver uma captura correspondente.

Os blocos catch e finalmente são partes ortogonais do bloco try. Você pode ter um ou ambos. Com o Java 7, você não poderá ter nenhum!


1

Você não tenta com esse programa? Irá finalmente bloquear e executar o bloco finalmente, mas a exceção não será tratada. Mas, essa exceção pode ser anulada no bloco finalmente!


1

O bloco finalmente é executado após a conclusão do bloco try. Se algo é lançado dentro do bloco try quando ele sai, o bloco final é executado.


0

Dentro do trybloco, escrevemos códigos que podem gerar uma exceção. O catchbloco é onde lidamos com a exceção. O finallybloco é sempre executado, independentemente de ocorrer ou não uma exceção.

Agora, se tivermos o bloco try-finalmente em vez do bloco try-catch-finalmente, a exceção não será tratada e, após o bloco try, em vez de o controle pegar o bloco, ele irá finalmente bloquear. Podemos usar o bloco try-finally quando queremos fazer nada com a exceção.


0

Independentemente da exceção lançada ou não no trybloco, o finallybloco será executado. A exceção não seria detectada.

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.