Java: verificação de exceção não verificada / verificada

Eu tenho lido sobre perguntas não verificadas versus perguntas checadas, nenhum dos resources on-line foi realmente claro sobre a diferença e quando usar os dois.

Pelo que entendi, ambos são lançados em tempo de execução, ambos representam estados de programa que estão fora dos limites esperados da lógica, mas as exceções verificadas devem ser explicitamente capturadas enquanto as não verificadas não.

Minha pergunta é, suponha que por causa do argumento eu tenho um método que divide dois números

double divide(double numerator, double denominator) { return numerator / denominator; } 

e um método que requer divisão em algum lugar

 void foo() { double a = divide(b, c); } 

Quem é responsável por verificar o caso do denominador sendo zero e uma exceção deve ser marcada ou desmarcada (ignorando as verificações de divisão incorporadas do Java)?

Então, o método de divisão seria declarado como é ou como

 double divide(double numerator, double denominator) throws DivideByZeroException { if(denominator == 0) throw DivideByZeroException else ... } void foo() { try{ double a = divide(b, c); } catch(DivideByZeroException e) {} } 

ou sem uma exceção verificada, como é:

 double divide(double numerator, double denominator) { if(denominator == 0) throw DivideByZeroException else ... } void foo() { if(c != 0) double a = divide(b, c); } 

e permitir que foo faça a divisão por zero check?

Este problema surgiu originalmente em um programa matemático que escrevi, no qual os usuários inseriam números e as classs lógicas realizavam cálculos. Eu nunca tinha certeza se a GUI deveria verificar imediatamente valores indevidos, ou se a lógica interna deveria pegá-los durante o cálculo e lançar exceções.

Tópico interessante, de fato!

Depois de ler e tentar muitas maneiras de lidar com erros em geral e exceções especificamente, aprendi a diferir entre os erros do programador e os erros esperados .

Os erros do programador nunca devem ser capturados, mas sim travar (!) Cedo e duramente. Um erro do programador é devido a uma falha lógica e a causa raiz deve ser corrigida.

Erros esperados devem sempre ser detectados. Além disso, quando um erro esperado é detectado, uma mensagem deve ser exibida para o usuário. Isso tem uma implicação importante – se um erro esperado não exibir um erro, é melhor verificar se o método será lançado em vez de deixá-lo ser lançado.

Então, aplicado ao seu exemplo, eu pensaria “Como isso deve parecer para o usuário?”

  1. Se uma mensagem de erro deve ser exibida (na saída do navegador, console, messagebox) eu lançaria uma exceção e a pegaria o mais próximo possível da interface do usuário e geraria a mensagem de erro.
  2. Se nenhuma mensagem de erro for exibida, eu verificaria a input e não a lançaria.

Em um sidenote: eu nunca jogo DivideByZeroException nem NullPointerException – eu deixo a JVM jogar isso para mim. Nesse caso, você pode preparar sua própria class de exceção ou usar uma exceção marcada interna adequada.

Minha discussão favorita sobre a diferença de filosofia entre exceções verificadas e não verificadas em Java:

http://www.javapractices.com/topic/TopicAction.do?Id=129

Suponha que uma exceção verificada seja lançada como resultado de uma operação matemática. Por exemplo, divisão (conforme seu post).
Isso significaria que toda divisão inteira deveria aparecer em um bloco try!
Na verdade, a divisão pode lançar uma ArithmeticException, exceção não verificada, para que não haja necessidade de capturá-la.
Na verdade, você não deve pegá-lo, pois é uma condição excepcional que ocorreu e geralmente só pode ser resolvida pela correção de código .
No seu caso, seu código deveria ter feito algo antes de realmente dividir por zero.
Se você alcançou a etapa em que você permite realmente fazer a divisão por zero, então não há nada que você possa fazer. O programa está errado e é melhor ser consertado do que tentar disfarçá-lo de alguma forma jogando / pegando uma exceção

As exceções Java são verificadas apenas pelo compilador, no entanto, os projetistas de java decidiram dividi-las em várias categorias, basicamente envolvendo a superclass sendo estendida

  • java.lang.Exception – conhecido como exceções verificadas
  • java.lang.RuntimeException conhecido como exceções não verificadas – como bônus java.land.RuntimeException estende java.lang.Exception (para facilitar o manuseio em blocos catch , e não apenas)
  • java.lang.Error – erros, também desmarcados e raramente precisavam ser manipulados pelo código de espaço do usuário, mas conhecê-los e sua variação é uma grande vantagem. Eles incluem (mais famosos): erro de binding, stackoverflow, falta de memory, erros de asserção
  • java.lang.Throwableverificado! e a mãe de todas as exceções, poucas precisam subclassificá-lo diretamente, mas algumas por razões desconhecidas

Portanto, é necessário declarar as exceções e cuidar da propagação adequada (no nível somente de compilation), as não verificadas são propagadas automaticamente e não se espera que o desenvolvedor forneça tratamento a menos que seja necessário.

Espera-se que os verificados ocorram e exijam detalhamento extra no código java, já fofo.

As piores práticas incluem: catch (Throwable t){} , por muitos motivos, geralmente os erros não devem ser manipulados a menos que sejam necessários e a maioria dos erros geralmente soletram a morte do thread de qualquer maneira.

Resposta curta como alguns prós e contras foram nomeados: É uma questão de estilo pessoal ou organizacional. Nenhum é funcionalmente melhor que o outro. Você (ou seu projeto) terá que tomar suas próprias decisões sobre usar exceções marcadas ou não verificadas, ou ambos.

O Java Tutorial da Oracle recomenda que você use exceções verificadas para todos os erros dos quais o aplicativo possa se recuperar e exceções não verificadas para os erros dos quais o aplicativo não pode se recuperar. Mas, pela minha experiência, a maioria dos aplicativos pode se recuperar da maioria (talvez não durante a boot) de exceções. A ação que falhou será abortada, mas o aplicativo permanecerá ativo.

Eu preferiria usar apenas exceções verificadas ou exceções não verificadas. A mistura pode resultar em confusão e uso inconsistente. Seja pragmático. Faça o que fizer sentido na sua situação.

Nunca lance explicitamente RuntimeException s. Se você acha que precisa deixar o runtime em vez de usar throw .