Estou preocupado que esta seja uma exceção de tempo de execução, portanto, provavelmente deve ser usada com moderação.
Caso de uso padrão:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
Mas parece que isso forçaria o seguinte design:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
Para voltar a ser uma exceção verificada.
Ok, mas vamos com isso. Se você fornecer informações incorretas, receberá um erro de tempo de execução. Em primeiro lugar, essa é uma política bastante difícil de implementar uniformemente, porque você pode ter que fazer a conversão exatamente o oposto:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
E pior - embora se 0 <= pct && pct <= 100
possa esperar que a verificação do código do cliente seja feita estaticamente, isso não é verdade para dados mais avançados, como um endereço de e-mail, ou pior, algo que precisa ser verificado em um banco de dados, portanto, em geral, o código do cliente não pode validar.
Basicamente, o que estou dizendo é que não vejo uma política consistente significativa para o uso de IllegalArgumentException
. Parece que não deve ser usado e devemos nos ater às nossas próprias exceções verificadas. Qual é um bom caso de uso para lançar isso?
fonte
Ao falar sobre "entrada incorreta", você deve considerar de onde vem a entrada.
Se for a entrada inserida por um usuário ou outro sistema externo que você não controla, você deve esperar que a entrada seja inválida e sempre valide-a. É perfeitamente normal lançar uma exceção verificada neste caso. Seu aplicativo deve 'se recuperar' dessa exceção, fornecendo uma mensagem de erro ao usuário.
Se a entrada se origina de seu próprio sistema, por exemplo, seu banco de dados ou alguma outra parte de seu aplicativo, você deve poder confiar que ela é válida (ela deveria ter sido validada antes de chegar lá). Nesse caso, é perfeitamente normal lançar uma exceção não verificada como IllegalArgumentException, que não deve ser capturada (em geral, você nunca deve capturar exceções não verificadas). É um erro do programador que o valor inválido tenha chegado lá em primeiro lugar;) Você precisa corrigi-lo.
fonte
Because an unchecked exception is meant to be thrown as a result of a programming error
me ajudou a limpar um monte de coisas na minha cabeça, obrigado :)Lançar exceções de tempo de execução "com moderação" não é realmente uma boa política - o Effective Java recomenda que você use exceções verificadas quando o chamador pode razoavelmente se recuperar . (O erro do programador é um exemplo específico: se um caso particular indicar erro do programador, você deve lançar uma exceção não verificada; você deseja que o programador tenha um rastreamento de pilha de onde o problema lógico ocorreu, e não tente resolvê-lo sozinho.)
Se não houver esperança de recuperação, sinta-se à vontade para usar exceções não verificadas; não há motivo para pegá-los, então está perfeitamente bem.
No entanto, não está 100% claro em seu exemplo em qual caso esse exemplo está em seu código.
fonte
foo(data)
pode ter acontecido como parte dafor(Data data : list) foo(data);
qual o chamador deseja que o maior número possível de operações, embora alguns dados estejam malformados. Inclui erros de programação também, se a falha do meu aplicativo significar que uma transação não será realizada, é provavelmente melhor, se isso significa que o resfriamento nuclear fica offline, isso é ruim.StackOverflowError
e tais são os casos dos quais o chamador não pode esperar uma recuperação razoável. Mas parece que qualquer caso de nível de lógica de aplicativo ou dados deve ser verificado. Isso significa que faça suas verificações de ponteiro nulo!Conforme especificado no tutorial oficial do oracle, ele afirma que:
Se eu tiver um aplicativo interagindo com o banco de dados usando
JDBC
, E tenho um método que leva o argumento comoint item
edouble price
. A . Espero ter expressado meu ponto de vista claramente ..price
item correspondente é lido da tabela do banco de dados. Simplesmente multiplico o número total deitem
adquiridos peloprice
valor e retorno o resultado. Embora eu tenha sempre certeza no meu final (final do aplicativo) que o valor do campo de preço na tabela nunca poderia ser negativo. Mas e se o valor do preço for negativo ? Isso mostra que há um problema sério com o lado do banco de dados. Talvez entrada de preço errada pela operadora. Esse é o tipo de problema que a outra parte do aplicativo que chama esse método não pode antecipar e não pode se recuperar dele. É umBUG
em seu banco de dados. Então eIllegalArguementException()
deve ser lançado neste caso, o que indicaria issothe price can't be negative
fonte
Qualquer API deve verificar a validade de cada parâmetro de qualquer método público antes de executá-lo:
Eles representam 99,9% das vezes erros no aplicativo porque ele está pedindo operações impossíveis então no final são bugs que deveriam travar o aplicativo (então é um erro irrecuperável).
Nesse caso, e seguindo a abordagem de falha rápida, você deve deixar o aplicativo terminar para evitar corromper o estado do aplicativo.
fonte
Trate
IllegalArgumentException
como uma verificação de pré - condições e considere o princípio de design: Um método público deve conhecer e documentar publicamente suas próprias pré-condições.Eu concordaria que este exemplo está correto:
Se EmailUtil for opaco , o que significa que há algum motivo para as pré-condições não poderem ser descritas para o usuário final, uma exceção verificada está correta. A segunda versão, corrigida para este design:
Se EmailUtil for transparente , por exemplo, talvez seja um método privado pertencente à classe em questão,
IllegalArgumentException
está correto se e somente se suas pré-condições podem ser descritas na documentação da função. Esta é uma versão correta também:Este projeto pode ir de qualquer maneira.
ParseException
. O método de nível superior aqui é nomeado, oscanEmail
que sugere que o usuário final pretende enviar e-mail não estudado, portanto, provavelmente está correto.IllegalArgumentException
. Embora não "marcada", a "verificação" se move para o Javadoc documentando a função, à qual o cliente deve aderir.IllegalArgumentException
onde o cliente não pode dizer que seu argumento é ilegal de antemão está errado.Uma observação sobre IllegalStateException : Isso significa que "o estado interno deste objeto (variáveis de instância privadas) não é capaz de executar esta ação." O usuário final não pode ver o estado privado, falando vagamente, ele tem precedência
IllegalArgumentException
no caso em que a chamada do cliente não tem como saber se o estado do objeto é inconsistente. Não tenho uma boa explicação sobre quando é preferível a exceções verificadas, embora coisas como inicializar duas vezes ou perder uma conexão de banco de dados que não é recuperada sejam exemplos.fonte