Fiquei surpreso recentemente ao descobrir que é possível ter uma declaração de retorno em um bloco finalmente em Java.
Parece que muitas pessoas pensam que é uma coisa ruim a fazer, conforme descrito em ' Não retorne em uma cláusula finalmente '. Arranhando um pouco mais fundo, também achei ' o retorno de Java nem sempre ', que mostra alguns exemplos bastante horríveis de outros tipos de controle de fluxo nos blocos finalmente.
Então, minha pergunta é: alguém pode me dar um exemplo em que uma declaração de retorno (ou outro controle de fluxo) em um bloco finalmente produz um código melhor / mais legível?
fonte
Eu realmente tive um tempo difícil para rastrear um bug que foi causado por isso. O código era algo como:
O que aconteceu é que a exceção foi lançada em algum outro código. Ele estava sendo capturado, registrado e reativado dentro do
somethingThatThrewAnException()
método. Mas a exceção não estava sendo propagada no passadoproblemMethod()
. Depois de muito tempo olhando para isso, finalmente o rastreamos até o método de retorno. O método de retorno no bloco finalmente estava basicamente impedindo a exceção que aconteceu no bloco try de se propagar, mesmo que não fosse capturado.Como outros já disseram, embora seja legal retornar de um bloco finalmente de acordo com a especificação Java, é uma coisa MAU e não deve ser feita.
fonte
O javac avisará o retorno, finalmente, se você usar o -Xlint: finalmente. Originalmente, o javac não emitiu avisos - se algo estiver errado com o código, ele deverá falhar na compilação. Infelizmente, a compatibilidade com versões anteriores significa que tolices engenhosas imprevistas não podem ser proibidas.
Exceções podem ser lançadas a partir de finalmente blocos, mas nesse caso o comportamento exibido é quase certamente o que você deseja.
fonte
A adição de estruturas de controle e retornos a finalmente {} blocos é apenas mais um exemplo de "apenas porque você pode" abusos que estão espalhados por praticamente todas as linguagens de desenvolvimento. Jason estava certo ao sugerir que poderia facilmente se tornar um pesadelo de manutenção - os argumentos contra retornos antecipados de funções se aplicam mais - então, neste caso de "retornos atrasados".
Finalmente, os blocos existem para um propósito, para permitir que você se arrume completamente, não importa o que aconteceu em todo o código anterior. Principalmente, isso é fechar / liberar ponteiros de arquivo, conexões com o banco de dados, etc.
Tudo o que afeta o retorno da função deve estar no bloco try {}. Mesmo se você tivesse um método pelo qual verificasse um estado externo, fizesse uma operação demorada e depois o verificasse novamente, caso se tornasse inválido, você ainda desejaria a segunda verificação dentro da tentativa {} - se ela permanecesse finalmente {} e a operação longa falhou, você estaria verificando esse estado uma segunda vez desnecessariamente.
fonte
Um simples teste Groovy:
Resultado:
Questão:
Um ponto interessante para mim foi ver como o Groovy lida com retornos implícitos. No Groovy é possível "retornar" de um método simplesmente deixando um valor no final (sem retorno). O que você acha que acontece, se você descomentar a linha runningThreads.remove (..) na instrução finalmente - isso substituirá o valor de retorno regular ("OK") e cobrirá a exceção ?!
fonte
Retornar de dentro de um
finally
bloco fará comexceptions
que se perca.Uma declaração de retorno dentro de um bloco final fará com que qualquer exceção que possa ser lançada no bloco try ou catch seja descartada.
De acordo com a especificação da linguagem Java:
Nota: Conforme JLS 14.17 - uma declaração de retorno sempre é concluída abruptamente.
fonte