Eu já vi essa pergunta, mas tenho mais algumas perguntas sobre o uso da assert
palavra - chave. Eu estava debatendo com alguns outros codificadores sobre o uso assert
. Para este caso de uso, havia um método que pode retornar nulo se determinados pré-requisitos forem atendidos. O código que escrevi chama o método, depois afirma que ele não retorna nulo e continua a usar o objeto retornado.
Exemplo:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Agora imagine que eu o uso assim:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Foi-me dito que eu deveria remover o assert
, que eles nunca deveriam ser usados no código de produção, somente no teste. Isso é verdade?
-ea
ou equivalente.Objects.requireNonNull
Java 8).Respostas:
Use
Objects.requireNonNull(Object)
para isso.No seu caso, isso seria:
Esta função é feita para os fins mencionados, ou seja, marque explicitamente o que não deve ser nulo; também em produção. O grande benefício é que você encontra valores nulos exatamente onde eles não devem ocorrer em primeiro lugar. Você terá menos problemas ao depurar problemas causados por valores nulos que foram passados em algum lugar onde não deveriam estar.
Outro benefício é a flexibilidade adicional em relação às verificações nulas, em contraste com
assert
. Emboraassert
seja uma palavra-chave para verificar um valor booleano,Objects.requireNonNull(Object)
é uma função e, portanto, pode ser incorporada ao código muito mais flexível e legível. Por exemplo:Lembre-se de que
Objects.requireNonNull(Object)
é exclusivamente para verificação nula ondeassert
é generalizada.assert
tem objetivos ligeiramente diferentes a esse respeito, ou seja, principalmente testes. Ele deve estar ativado, para que você possa testá-lo e desativá-lo para produção. De qualquer forma, não o use para código de produção. Isso pode desacelerar o aplicativo com validações desnecessárias e complicadas destinadas a testes. Use-o para separar verificações apenas de testes das verificações destinadas também à produção.Confira a documentação oficial para obter detalhes sobre
assert
.fonte
O mais importante a ser lembrado sobre as asserções é que elas podem ser desabilitadas, portanto nunca assuma que serão executadas.
Para compatibilidade com versões anteriores, a JVM desabilita a validação de asserção por padrão. Eles devem ser ativados explicitamente usando o argumento da linha de comandos -enableassertions ou seu atalho -ea:
Portanto, não é uma boa prática confiar neles.
Como as asserções não são ativadas por padrão, você nunca pode assumir que elas serão executadas quando usadas no código. Portanto, você deve sempre verificar valores nulos e opcionais vazios, evitar usar asserções para verificar entradas em um método público e usar uma exceção não verificada ... Em geral, faça todas as verificações como se a asserção não estivesse lá.
fonte
Certamente o que lhe disseram é uma mentira descarada. Aqui está o porquê.
As asserções são desativadas por padrão se você acabou de executar a jvm independente. Quando estão desabilitados, não possuem área ocupada e, portanto, não afetam seu aplicativo de produção. No entanto, eles provavelmente são seus melhores amigos ao desenvolver e testar seu código, e a maioria dos corredores da estrutura de teste habilita asserções (o JUnit habilita); portanto, seu código de asserção é executado quando você executa seus testes de unidade, ajudando a detectar possíveis erros anteriormente (por exemplo, você pode adicionar declarações para algumas verificações de limites da lógica de negócios e isso ajudará a detectar algum código que use valores inadequados).
Dito isto, como a outra resposta sugere, exatamente por esse motivo (eles nem sempre estão ativados), você não pode confiar em asserções para fazer algumas verificações vitais, ou (especialmente!) Manter qualquer estado.
Para um exemplo interessante de como você pode usar asserts, dê uma olhada aqui - no final do arquivo, há um método
singleThreadedAccess()
que é chamado a partir da declaração assert na linha 201 e existe para capturar qualquer acesso multithread em potencial nos testes.fonte
As outras respostas já cobrem isso bem o suficiente, mas existem outras opções.
Por exemplo, o Spring possui um método estático:
org.springframework.util.Assert.notNull(obj)
Existem outras bibliotecas com
Assert.something()
métodos próprios também. Também é bem simples de escrever.No entanto, lembre-se de quais exceções você lança se este for um serviço da web. O método anterior mencionado, por exemplo, lança um
IllegalArgumentException
que por padrão no Spring retorna um 500.No caso de um serviço da Web, esse erro geralmente não é interno do servidor e não deve ser um 500, mas um 400, o que é uma solicitação incorreta.
fonte
assert
é: obter uma falha imediata com um arquivo principal produzido para que você possa executar um post-mortem com seu depurador favorito no local em que a condição foi violada.assert
jogar. Interessante. A versão C / C ++ não faz isso. Imediatamente gera um sinal de que a) mata o processo eb) cria um dump principal. Faz isso por um motivo: é muito simples depurar uma falha de declaração, porque você ainda tem todas as informações sobre a pilha de chamadas disponíveis. A definiçãoassert
de lançar uma exceção, que pode ser capturada (não) intencionalmente programaticamente, derrota o objetivo, imho.Throwable
. Eles sempre podem ser pegos. Se isso é bom ou não, eu não sei. Eu acho que depende. Muitos programas Java são serviços da Web, e seria indesejável travar por quase qualquer motivo, portanto, quase tudo é capturado e registrado. Uma das grandes coisas é o rastreamento de pilha, e isso geralmente é suficiente para diagnosticar o motivo de uma exceção ou erro por si só.Use afirmações generosamente sempre que isso o ajudar a detectar erros de programação, como erros.
Não use assert para capturar algo que possa acontecer logicamente, ou seja, entrada mal formatada. Use assert somente quando o erro for irrecuperável.
Não coloque nenhuma lógica de produção no código que é executado quando a asserção é verificada. Se o seu software for bem escrito, isso é trivialmente verdadeiro, mas se não for, você poderá ter efeitos colaterais sutis e comportamento geral diferente com as afirmações ativadas e desativadas.
Se sua empresa tem "código de teste" e "código de produção" fazendo a mesma coisa, mas como bases de código diferentes (ou estágios diferentes de edição), saia daí e nunca mais volte. Tentar consertar esse nível de incompetência é provavelmente uma perda de tempo. Se sua empresa não colocar nenhuma declaração de afirmação fora do código dos testes, diga-lhes que afirmações estão desabilitadas na produção e que, se não estiverem, corrigir esse erro agora é sua primeira prioridade.
O valor das declarações deve ser usado precisamente dentro da lógica de negócios e não apenas no conjunto de testes. Isso facilita a realização de muitos testes de alto nível que não precisam ser explicitamente testados para passar por grandes partes do seu código e acionar todas essas asserções. Em alguns de meus projetos, os testes típicos nem sequer afirmam nada, eles apenas ordenaram que um cálculo acontecesse com base em entradas específicas e isso causou centenas de afirmações a serem verificadas e problemas a serem encontrados, mesmo em pequenos pedaços de lógica no fundo.
fonte
Você pode usar afirmar a qualquer momento. O debate que vem é quando usar. Por exemplo no guia :
fonte