Quando usar exceções em Java (exemplo)

Eu sei que isso seria uma má prática, embora eu saiba que não seria capaz de explicar por quê.

int [] intArr = ... ... try{ int i = 0; while(true){ System.out.println(intArr[i++]); } }catch(ArrayIndexOutOfBoundsException e){} 

Eu acho que você só deve usar exceções para coisas que não deveriam acontecer . Estou fazendo essa pergunta porque acho que estou usando exceções erradas às vezes. Se a sua programação está executando um caso padrão , exceções devem ser lançadas?

Isso parece relacionado: Prevenção de exceções vs. captura de exceções em Java

Você está certo: as exceções são para casos excepcionais . Usá-los para controlar o stream de controle normal não é apenas obscurecer a intenção do código (o que já seria suficiente para desqualificá-lo), mas também é muito mais lento, já que lançar e capturar exceções é caro.

O idioma padrão (no Java5 e acima) está usando um loop foreach :

 for (int i : intArr) { System.out.println(i); } 

Está errado porque você sabe que eventualmente o loop alcançará o último elemento do intArr , então não há nada de excepcional nisso, você está realmente esperando esse comportamento.

Capturar exceções é apenas uma prática ruim quando se trata de uma RuntimeException . O ArrayIndexOutOfBoundsException que você está tentando capturar é um.

RuntimeExceptions identificam problemas recuperáveis ​​programaticamente que são causados ​​por falhas no stream de código. Você não deve consertá-los capturando-os, mas escrevendo código apropriado e fazendo uso de instruções de controle de stream como if/else , while , for , etc.

Veja também:

  • Quando jogar qual exceção?
  • Tutorial de exceções

Como sempre “depende” e você encontrará muitas opiniões diferentes. Aqui é meu

  • As exceções se enquadram em duas categorias gerais.
    • Coisas que você pode razoavelmente antecipar e manipular (FileNotFoundException)
    • Coisas que você geralmente não antipicula assumindo código perfeito (ArrayIndexOutOfBounds)

Você esperaria geralmente lidar com a primeira categoria e não o último. Este último é geralmente erros de programação.

Seu exemplo cai no último caso, um erro de programação. A exceção destina-se a fornecer boas informações sobre a falha no tempo de execução, não atuar como um stream de controle.

Algumas pessoas dirão que a primeira é uma exceção verificada e a segunda é desmarcada. Eu discordaria disso. Eu quase sempre acho exceções verificadas uma dor na realidade como você quase sempre acaba pegando / wrap / rethrow para outro tipo de exceção. Ao lançar exceções e definir minhas próprias classs de exceção, quase sempre uso desmarcado.

Você está certo. Exceções não devem ser usadas para lidar com o stream do processo.

Comer exceções do jeito que você faz é geralmente considerado uma prática ruim: se você não tem que fazer nenhum outro tratamento, você pode registrá-lo.

Apenas em situações excepcionais como

  • quando um método não pode fazer o que é suposto fazer
  • não para controlar o stream de execução

Exceções devem capturar algo excepcional, registrá-lo e recuperar, se possível.

Se for parte do stream normal do programa, você deve lidar com isso normalmente.

Exceções são para exceções no código. Não para casos padrão.

no entanto, há um problema mais sério com o seu código, é mais lento o que seria sem o uso de exceção. Criar a exceção, lançando a exceção e capturando a exceção, leva CPU e MEMORY adicionais.

Além disso, o código fica mais difícil de ler para outros programadores que apenas esperam exceções para serem lançados em casos de erro.

Chegar ao final de um array não é um caso excepcional. Você sabe o tamanho antes de iniciar o loop, portanto, use um idioma padrão.

 for(int i = 0; i < intArr.length; ++i) { System.out.println(intArr[i]); }