Como lidar com exceções Java da maneira certa

Como lidar com exceções Java da maneira certa

Como um novato em programação, o conceito de manipulação de exceção pode ser difícil de entender. Não que o conceito em si seja difícil, mas a terminologia pode fazer com que pareça mais avançado do que realmente é. E é um recurso tão poderoso que está sujeito a uso indevido e abuso.





Neste artigo, você aprenderá o que são exceções, por que são importantes, como usá-las e erros comuns a serem evitados. A maioria das linguagens modernas tem algum tipo de tratamento de exceção, portanto, se você deixar o Java, pode levar a maioria dessas dicas com você.





Compreendendo as exceções Java

Em Java, um exceção é um objeto que indica que algo anormal (ou 'excepcional') ocorreu durante a execução de seu aplicativo. Essas exceções são jogado , o que basicamente significa que um objeto de exceção é criado (semelhante a como os erros são 'gerados').





A beleza é que você pode pegar lançadas exceções, que permitem lidar com a condição anormal e permitir que seu aplicativo continue em execução como se nada tivesse dado errado. Por exemplo, enquanto um ponteiro nulo em C pode travar seu aplicativo, Java permite que você lance e pegue

NullPointerException

s antes que uma variável nula tenha a chance de causar um travamento.



Lembre-se, uma exceção é apenas um objeto, mas com uma característica importante: deve ser estendida a partir do

Exception

classe ou qualquer subclasse de





Exception

. Embora o Java tenha todos os tipos de exceções integradas, você também pode criar as suas próprias, se desejar. Alguns dos exceções Java mais comuns incluir:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Então, o que acontece quando você lança uma exceção?





Primeiro, o Java olha dentro do método imediato para ver se há código que trata o tipo de exceção que você lançou. Se um manipulador não existir, ele examina o método que chamou o método atual para ver se existe um identificador nele. Caso contrário, analisa o método que chamou naquela método e, em seguida, o próximo método, etc. Se a exceção não for detectada, o aplicativo imprimirá um rastreamento de pilha e, em seguida, travará. (Na verdade, é mais sutil do que simplesmente travar, mas esse é um tópico avançado além do escopo deste artigo.)

PARA rastreamento de pilha é uma lista de todos os métodos que o Java percorreu enquanto procurava um manipulador de exceção. Esta é a aparência de um rastreamento de pilha:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Podemos extrair muito disso. Primeiro, a exceção lançada foi um

NullPointerException

. Ocorreu no

getTitle()

método na linha 16 de Book.java. Esse método foi chamado de

getBookTitles()

na linha 25 de Author.java. Este método foi chamado de

main()

na linha 14 do Bootstrap.java. Como você pode ver, saber de tudo isso torna a depuração mais fácil.

Mas, novamente, o verdadeiro benefício das exceções é que você pode 'manipular' a condição anormal capturando a exceção, configurando as coisas corretamente e reiniciando o aplicativo sem travar.

Usando exceções Java no código

Digamos que você tem

someMethod()

que pega um número inteiro e executa alguma lógica que pode falhar se o número inteiro for menor que 0 ou maior que 100. Este pode ser um bom lugar para lançar uma exceção:

centro de ação do windows 10 não exibido
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

Para capturar essa exceção, você precisa ir para onde

someMethod()

é chamado e usa o bloco try-catch :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

Tudo dentro do Experimente bloco será executado em ordem até que uma exceção seja lançada. Assim que uma exceção é lançada, todas as instruções subsequentes são ignoradas e a lógica do aplicativo imediatamente salta para o pegar bloquear.

Em nosso exemplo, inserimos o bloco try e chamamos imediatamente

someMethod()

. Uma vez que 200 não está entre 0 e 100, um

IllegalArgumentException

é lançado. Isso termina imediatamente a execução de

someMethod()

, ignora o resto da lógica no bloco try (

someOtherMethod()

nunca é chamado) e retoma a execução dentro do bloco catch.

O que aconteceria se nós ligássemos

someMethod(50)

em vez de? o

IllegalArgumentException

nunca seria lançado.

someMethod()

seria executado normalmente. O bloco try seria executado normalmente, chamando

someOtherMethod()

quando someMethod () for concluído. Quando

someOtherMethod()

termina, o bloco de captura seria ignorado e

callingMethod()

iria continuar.

Observe que você pode ter vários blocos catch por bloco try:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

Observe também que um opcional finalmente bloco também existe:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

O código em um bloco finally é sempre executado não importa o quê. Se você tiver uma instrução return no bloco try, o bloco finally será executado antes de retornar do método. Se você lançar outra exceção no bloco catch, o bloco finally será executado antes que a exceção seja lançada.

Você deve usar o bloco finally quando houver objetos que precisam ser limpos antes que o método termine. Por exemplo, se você abriu um arquivo no bloco try e posteriormente lançou uma exceção, o bloco finally permite fechar o arquivo antes de sair do método.

Observe que você pode ter um bloco finally sem um bloco catch:

public void method() {
try {
// ...
} finally {
// ...
}
}

Isso permite que você faça qualquer limpeza necessária enquanto permite que as exceções lançadas propaguem a pilha de invocação do método (ou seja, você não quer lidar com a exceção aqui, mas ainda precisa limpar primeiro).

Exceções verificadas vs. não verificadas em Java

Ao contrário da maioria das linguagens, Java distingue entre exceções verificadas e exceções não verificadas (por exemplo, C # só tem exceções não verificadas). Uma exceção verificada deve ser capturado no método onde a exceção é lançada ou então o código não compilará.

Para criar uma exceção marcada, estenda de

Exception

. Para criar uma exceção não verificada, estenda de

RuntimeException

.

Qualquer método que lança uma exceção verificada deve denotar isso na assinatura do método usando o arremessa palavra-chave. Já que o Java está integrado

IOException

é uma exceção verificada, o seguinte código não compilará:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Você deve primeiro declarar que ele lança uma exceção verificada:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Observe que um método pode ser declarado como lançando uma exceção, mas nunca realmente lança uma exceção. Mesmo assim, a exceção ainda precisará ser capturada ou o código não será compilado.

Quando você deve usar exceções marcadas ou não verificadas?

A documentação oficial do Java tem um página nesta questão . Ele resume a diferença com uma regra prática sucinta: 'Se for razoável esperar que um cliente se recupere de uma exceção, torne-o uma exceção verificada. Se um cliente não puder fazer nada para se recuperar da exceção, torne-a uma exceção não verificada. '

Mas esta diretriz pode estar desatualizada. Por um lado, as exceções verificadas resultam em um código mais robusto. Por outro lado, nenhuma outra linguagem verificou exceções da mesma maneira que Java, o que mostra duas coisas: uma, o recurso não é útil o suficiente para que outras linguagens o roubem e, segundo, você pode absolutamente viver sem elas. Além disso, as exceções verificadas não funcionam bem com expressões lambda introduzidas no Java 8.

Diretrizes para o uso de exceções Java

As exceções são úteis, mas facilmente mal utilizadas e abusadas. Aqui estão algumas dicas e práticas recomendadas para ajudá-lo a evitar bagunçá-los.

  • Prefira exceções específicas a exceções gerais. Use NumberFormatException sobre IllegalArgumentException quando possível, caso contrário, use IllegalArgumentException sobre RuntimeException quando possivel.
  • Nunca pegue Throwable ! O Exception classe realmente estende Throwable , e o bloco catch realmente funciona com Throwable ou qualquer classe que estenda Throwable. No entanto, o Error classe também estende Throwable , e você nunca mais vai querer pegar um Error porque Error s indicam problemas graves irrecuperáveis.
  • Nunca pegue Exception ! InterruptedException estende Exception , portanto, qualquer bloco que captura Exception também capturará InterruptedException , e essa é uma exceção muito importante com a qual você não quer mexer (especialmente em aplicativos multithread), a menos que saiba o que está fazendo. Se você não souber qual exceção capturar, considere não capturar nada.
  • Use mensagens descritivas para facilitar a depuração. Ao lançar uma exceção, você pode fornecer um String mensagem como um argumento. Esta mensagem pode ser acessada no bloco catch usando Exception.getMessage() método, mas se a exceção nunca for detectada, a mensagem também aparecerá como parte do rastreamento de pilha.
  • Tente não capturar e ignorar exceções. Para contornar a inconveniência das exceções verificadas, muitos programadores novatos e preguiçosos configuram um bloco catch, mas o deixam vazio. Mau! Sempre lide com isso com elegância, mas se não puder, pelo menos imprima um rastreamento de pilha para saber que a exceção foi lançada. Você pode fazer isso usando Exception.printStackTrace() método.
  • Cuidado com o uso excessivo de exceções. Quando você tem um martelo, tudo parece um prego. Quando você aprende sobre exceções pela primeira vez, pode se sentir obrigado a transformar tudo em uma exceção ... até o ponto em que a maior parte do fluxo de controle de seu aplicativo se reduz ao tratamento de exceções. Lembre-se de que as exceções são destinadas a ocorrências 'excepcionais'!

Agora você deve estar confortável o suficiente com as exceções para entender o que são, por que são usadas e como incorporá-las em seu próprio código. Se você não entender totalmente o conceito, tudo bem! Demorei um pouco para 'clicar' na minha cabeça, então não sinta que precisa se apressar. Sem pressa.

Tem alguma pergunta? Sabe de alguma outra dica relacionada a exceções que eu perdi? Compartilhe-os nos comentários abaixo!

Compartilhado Compartilhado Tweet O email Como criar um diagrama de fluxo de dados para visualizar os dados de qualquer projeto

Os diagramas de fluxo de dados (DFD) de qualquer processo ajudam a entender como os dados fluem da origem para o destino. Veja como criá-lo!

Leia a seguir
Tópicos relacionados
  • Programação
  • Java
Sobre o autor Joel Lee(1524 artigos publicados)

Joel Lee é o Editor-chefe da MakeUseOf desde 2018. Ele tem um B.S. em Ciência da Computação e mais de nove anos de experiência profissional em redação e edição.

como selecionar tudo de uma cor no photoshop
Mais de Joel Lee

Assine a nossa newsletter

Junte-se ao nosso boletim informativo para dicas de tecnologia, análises, e-books grátis e ofertas exclusivas!

Clique aqui para se inscrever