Eu uso object != null
muito para evitar NullPointerException
.
Existe uma boa alternativa para isso?
Por exemplo, eu costumo usar:
if (someobject != null) {
someobject.doCalc();
}
Isto verifica para um NullPointerException
para o someobject
objecto no fragmento acima.
Observe que a resposta aceita pode estar desatualizada, consulte https://stackoverflow.com/a/2386013/12943 para obter uma abordagem mais recente.
java
object
nullpointerexception
null
Goran Martinic
fonte
fonte
Option
tipo de Scala é marcado pela falta de vontade da língua em controlar ou proibirnull
. Eu mencionei isso no hackernews e recebi votos negativos e disse que "ninguém usa null no Scala de qualquer maneira". Adivinha, já estou encontrando nulos no Scala escrito por um colega de trabalho. Sim, eles estão "fazendo errado" e deve ser educado sobre isso, mas a verdade é sistema do tipo da linguagem deve proteger-me com isso e isso não acontece :(Respostas:
Isso para mim parece um problema razoavelmente comum que os desenvolvedores juniores a intermediários tendem a enfrentar em algum momento: eles não sabem ou não confiam nos contratos dos quais estão participando e buscam na defensiva por nulos. Além disso, ao escrever seu próprio código, eles tendem a confiar no retorno de nulos para indicar algo, exigindo que o chamador verifique nulos.
Em outras palavras, há duas instâncias em que a verificação nula é exibida:
Onde nulo é uma resposta válida em termos do contrato; e
Onde não é uma resposta válida.
(2) é fácil. Use
assert
instruções (asserções) ou permita falha (por exemplo, NullPointerException ). As asserções são um recurso Java altamente subutilizado que foi adicionado na 1.4. A sintaxe é:ou
onde
<condition>
é uma expressão booleana e<object>
é um objeto cujatoString()
saída do método será incluída no erro.Uma
assert
instrução lança umError
(AssertionError
) se a condição não for verdadeira. Por padrão, Java ignora asserções. Você pode ativar asserções passando a opção-ea
para a JVM. Você pode ativar e desativar asserções para classes e pacotes individuais. Isso significa que você pode validar o código com as asserções durante o desenvolvimento e o teste e desabilitá-las em um ambiente de produção, embora meus testes tenham demonstrado quase nenhum impacto no desempenho das asserções.Não usar afirmações nesse caso é bom porque o código falhará, o que acontecerá se você usar afirmações. A única diferença é que, com afirmações, isso pode acontecer mais cedo, de maneira mais significativa e possivelmente com informações extras, o que pode ajudá-lo a descobrir por que isso aconteceu se você não estava esperando.
(1) é um pouco mais difícil. Se você não tem controle sobre o código para o qual está ligando, está preso. Se nulo é uma resposta válida, você deve procurá-la.
No entanto, se é o código que você controla (e esse geralmente é o caso), é uma história diferente. Evite usar nulos como resposta. Com métodos que retornam coleções, é fácil: retornar coleções vazias (ou matrizes) em vez de nulos praticamente o tempo todo.
Com as não coleções, pode ser mais difícil. Considere isso como um exemplo: se você possui estas interfaces:
onde o Analisador pega a entrada bruta do usuário e encontra algo para fazer, talvez se você estiver implementando uma interface de linha de comando para algo. Agora você pode fazer com que o contrato retorne nulo se não houver uma ação apropriada. Isso leva à verificação nula da qual você está falando.
Uma solução alternativa é nunca retornar nulo e, em vez disso, usar o padrão Null Object :
Comparar:
para
que é um design muito melhor porque leva a um código mais conciso.
Dito isso, talvez seja inteiramente apropriado que o método findAction () lance uma exceção com uma mensagem de erro significativa - especialmente nesse caso em que você depende da entrada do usuário. Seria muito melhor para o método findAction lançar uma exceção do que para o método de chamada explodir com uma simples NullPointerException sem explicação.
Ou, se você acha que o mecanismo de tentativa / captura é muito feio, em vez de Não fazer nada, sua ação padrão deve fornecer feedback ao usuário.
fonte
Se você usar (ou planejar usar) um Java IDE como JetBrains IntelliJ IDEA , Eclipse ou Netbeans ou uma ferramenta como findbugs, poderá usar anotações para resolver esse problema.
Basicamente, você tem
@Nullable
e@NotNull
.Você pode usar métodos e parâmetros, como este:
ou
O segundo exemplo não será compilado (no IntelliJ IDEA).
Quando você usa a primeira
helloWorld()
função em outro trecho de código:Agora, o compilador IntelliJ IDEA informará que a verificação é inútil, pois a
helloWorld()
função nunca retornaránull
.Usando parâmetro
se você escrever algo como:
Isso não será compilado.
Último exemplo usando
@Nullable
Fazendo isso
E você pode ter certeza de que isso não acontecerá. :)
É uma boa maneira de permitir que o compilador verifique algo mais do que normalmente faz e impor seus contratos para serem mais fortes. Infelizmente, não é suportado por todos os compiladores.
No IntelliJ IDEA 10.5 e posteriores, eles adicionaram suporte para qualquer outro
@Nullable
@NotNull
implementações.Ver postagem no blog Anotações @ flexíveis e configuráveis @ Nullable / @ NotNull .
fonte
@NotNull
,@Nullable
E outras anotações nullness fazem parte do JSR 305 . Você também pode usá-los para detectar possíveis problemas com ferramentas como o FindBugs .@NotNull
&@Nullable
estejam no pacotecom.sun.istack.internal
. (Eu acho que eu com.sun associado com avisos sobre usando uma API proprietária.)@NotNull
e@Nullable
são, é que elas se degradam muito bem quando o código-fonte é criado por um sistema que não as entende. Portanto, com efeito, o argumento de que o código não é portátil pode ser inválido - se você usar um sistema que suporte e compreenda essas anotações, obterá o benefício adicional de uma verificação mais rigorosa dos erros, caso contrário, você obtém menos, mas seu código ainda deve compilar bem, e a qualidade do seu programa em execução é A MESMA, porque essas anotações não foram aplicadas em tempo de execução de qualquer maneira. Além disso, todos os compiladores são personalizados ;-) #Se valores nulos não forem permitidos
Se seu método for chamado externamente, comece com algo como isto:
Então, no restante desse método, você saberá que
object
não é nulo.Se for um método interno (não parte de uma API), apenas documente que não pode ser nulo, e é isso.
Exemplo:
No entanto, se o seu método apenas passar o valor, e o próximo método o transmitir, etc., isso pode se tornar problemático. Nesse caso, você pode querer verificar o argumento como acima.
Se nulo for permitido
Isso realmente depende. Se achar que muitas vezes faço algo assim:
Então eu ramifico e faço duas coisas completamente diferentes. Não há um trecho de código feio, porque eu realmente preciso fazer duas coisas diferentes, dependendo dos dados. Por exemplo, devo trabalhar na entrada ou devo calcular um bom valor padrão?
Na verdade, é raro eu usar o idioma "
if (object != null && ...
".Pode ser mais fácil dar exemplos, se você mostrar exemplos de onde normalmente usa o idioma.
fonte
throw new IllegalArgumentException("object==null")
Uau, eu quase odeio adicionar outra resposta quando temos 57 maneiras diferentes de recomendar o
NullObject pattern
, mas acho que algumas pessoas interessadas nesta pergunta talvez gostem de saber que existe uma proposta na tabela para o Java 7 adicionar "segurança nula" tratamento" - uma sintaxe simplificada para lógica if-not-equal-null.O exemplo dado por Alex Miller é assim:
Os
?.
meios apenas fazem a referência do identificador esquerdo se não for nulo; caso contrário, avalie o restante da expressão comonull
. Algumas pessoas, como Dick Wall, membro do Java Posse e os eleitores da Devoxx, realmente amam essa proposta, mas também há oposição, alegando que ela realmente incentivará um maior usonull
como valor sentinela.Atualização: Uma proposta oficial para um operador com segurança nula no Java 7 foi enviada no Project Coin. A sintaxe é um pouco diferente do exemplo acima, mas é a mesma noção.
Atualização: a proposta do operador com segurança nula não foi incluída no Project Coin. Portanto, você não verá esta sintaxe no Java 7.
fonte
Se valores indefinidos não forem permitidos:
Você pode configurar seu IDE para avisá-lo sobre a possibilidade de cancelamento de referência nula. Por exemplo, no Eclipse, consulte Preferências> Java> Compilador> Erros / avisos / análise nula .
Se valores indefinidos forem permitidos:
Se você deseja definir uma nova API na qual valores indefinidos fazem sentido , use o Padrão de Opção (pode ser familiar nas linguagens funcionais). Tem as seguintes vantagens:
Java 8 tem uma
Optional
classe interna (recomendado); para versões anteriores, existem alternativas de biblioteca, por exemplo, Guava 'Optional
ou FunctionalJava 'Option
. Porém, como muitos padrões de estilo funcional, o uso de Option em Java (até 8) resulta em bastante clichê, que você pode reduzir usando uma linguagem JVM menos detalhada, como Scala ou Xtend.Se você precisar lidar com uma API que possa retornar nulos , não poderá fazer muito em Java. Xtend e Groovy têm o operador Elvis
?:
e o operador de desreferência com segurança nula?.
, mas observe que isso retorna nulo no caso de uma referência nula; portanto, apenas "adia" a manipulação adequada de nulo.fonte
Somente para esta situação -
Não verificando se uma variável é nula antes de chamar um método equals (um exemplo de comparação de string abaixo):
resultará em um
NullPointerException
sefoo
não existir.Você pode evitar isso se comparar seus
String
s assim:fonte
<object that you know that is not null>.equals(<object that might be null>);
. Funciona para outros métodos, excetoequals
se você conhece o contrato e esses métodos podem manipularnull
parâmetros.Com o Java 8, vem a nova
java.util.Optional
classe que, sem dúvida, resolve alguns dos problemas. Pode-se dizer pelo menos que isso melhora a legibilidade do código e, no caso de APIs públicas, torna o contrato da API mais claro para o desenvolvedor do cliente.Eles funcionam assim:
Um objeto opcional para um determinado tipo (
Fruit
) é criado como o tipo de retorno de um método. Pode estar vazio ou conter umFruit
objeto:Agora observe este código em que pesquisamos uma lista de
Fruit
(fruits
) para uma determinada instância Fruit:Você pode usar o
map()
operador para executar uma computação - ou extrair um valor de - um objeto opcional.orElse()
permite fornecer um fallback para valores ausentes.Obviamente, a verificação do valor nulo / vazio ainda é necessária, mas pelo menos o desenvolvedor está consciente de que o valor pode estar vazio e o risco de esquecer de verificar é limitado.
Em uma API criada do zero, usando
Optional
sempre que um valor de retorno estiver vazio e retornando um objeto simples somente quando não puder sernull
(convenção), o código do cliente pode abandonar as verificações nulas nos valores de retorno de objetos simples ...É claro
Optional
que também poderia ser usado como argumento de método, talvez uma maneira melhor de indicar argumentos opcionais do que 5 ou 10 métodos de sobrecarga em alguns casos.Optional
oferece outros métodos convenientes, como oorElse
que permite o uso de um valor padrão eifPresent
que funciona com expressões lambda .Convido você a ler este artigo (minha principal fonte para escrever esta resposta), na qual são explicadas tanto a
NullPointerException
(e geralmente o ponteiro nulo) problemática quanto a solução (parcial) apresentada porOptional
: Objetos Opcionais Java .fonte
if(optional.isPresent()){ optional.get(); }
em vez deoptional.ifPresent(o -> { ...})
Dependendo do tipo de objeto que você está verificando, você pode usar algumas das classes nos apache commons, como: apache commons lang e apache commons collections
Exemplo:
ou (dependendo do que você precisa verificar):
A classe StringUtils é apenas uma dentre muitas; existem algumas boas classes nos bens comuns que fazem manipulação segura nula.
Segue um exemplo de como você pode usar validação nula em JAVA ao incluir a biblioteca apache (commons-lang-2.4.jar)
E se você estiver usando o Spring, o Spring também possui a mesma funcionalidade em seu pacote, consulte a biblioteca (spring-2.4.6.jar)
Exemplo de como usar este classf estático da spring (org.springframework.util.Assert)
fonte
Você precisa verificar o objeto! = Null apenas se desejar lidar com o caso em que o objeto pode ser nulo ...
Há uma proposta para adicionar novas anotações no Java7 para ajudar com parâmetros nulos / não nulos: http://tech.puredanger.com/java7/#jsr308
fonte
Sou fã do código "falhar rápido". Pergunte a si mesmo - você está fazendo algo útil no caso em que o parâmetro é nulo? Se você não tiver uma resposta clara para o que seu código deve fazer nesse caso ... Ou seja, nunca deve ser nulo em primeiro lugar, ignore-o e permita que uma NullPointerException seja lançada. O código de chamada fará tanto sentido para um NPE quanto para um IllegalArgumentException, mas será mais fácil para o desenvolvedor depurar e entender o que deu errado se um NPE for lançado, em vez de seu código tentar executar alguma outra contingência inesperada lógica - que acaba resultando na falha da aplicação.
fonte
A estrutura de coleções do Google oferece uma maneira boa e elegante de realizar a verificação nula.
Existe um método em uma classe de biblioteca como esta:
E o uso é (com
import static
):Ou no seu exemplo:
fonte
getThing().getItsThing().getOtherThing().wowEncapsulationIsBroken().setLol("hi");
Às vezes, você tem métodos que operam em seus parâmetros que definem uma operação simétrica:
Se você sabe que b nunca pode ser nulo, basta trocá-lo. É mais útil para iguais: em vez de
foo.equals("bar");
fazer melhor"bar".equals(foo);
.fonte
equals
(pode ser qualquer método) manipulará o nulo corretamente. Realmente, tudo o que isso está fazendo é passar a responsabilidade para outra pessoa (ou outro método).equals
(ou qualquer outro método) precisa verificar denull
qualquer maneira. Ou declare explicitamente que não.Em vez de Padrão de Objeto Nulo - que tem seus usos - você pode considerar situações em que o objeto nulo é um erro.
Quando a exceção é lançada, examine o rastreamento da pilha e trabalhe com o bug.
fonte
Nulo não é um 'problema'. É parte integrante de um conjunto completo de ferramentas de modelagem. O software tem como objetivo modelar a complexidade do mundo e nulo carrega seu fardo. Nulo indica 'Sem dados' ou 'Desconhecido' em Java e similares. Portanto, é apropriado usar nulos para esses fins. Não prefiro o padrão 'Objeto nulo'; Eu acho que surge o problema de ' quem guardará os guardiões '.
Se você me perguntar qual é o nome da minha namorada, eu direi que não tenho namorada. Na linguagem Java retornarei nulo. Uma alternativa seria lançar uma exceção significativa para indicar algum problema que não pode ser (ou não
Para uma "pergunta desconhecida", dê "resposta desconhecida". (Seja nulo com segurança quando isso estiver correto do ponto de vista comercial) A verificação de argumentos como nulo uma vez dentro de um método antes do uso evita que vários chamadores os verifiquem antes de uma chamada.
O anterior leva ao fluxo lógico normal para não obter uma foto de uma namorada inexistente da minha biblioteca de fotos.
E se encaixa com a nova API Java que está chegando (ansiosa)
Embora seja bastante "fluxo comercial normal" não encontrar fotos armazenadas no banco de dados para alguma pessoa, eu costumava usar pares como abaixo em outros casos
E não deteste digitar
<alt> + <shift> + <j>
(gere javadoc no Eclipse) e escreva três palavras adicionais para sua API pública. Isso será mais do que suficiente para todos, exceto aqueles que não leem a documentação.ou
Esse é um caso bastante teórico e, na maioria dos casos, você deve preferir a API segura java null (caso seja lançada em mais 10 anos), mas
NullPointerException
é uma subclasse de umException
. Portanto, é uma formaThrowable
que indica as condições que um aplicativo razoável pode querer capturar ( javadoc )! Para usar a primeira vantagem das exceções e separar o código de tratamento de erros do código 'regular' (de acordo com os criadores de Java ), é apropriado, quanto a mim, capturarNullPointerException
.Perguntas podem surgir:
Q. E se
getPhotoDataSource()
retornar nulo?R. Depende da lógica de negócios. Se não encontrar um álbum de fotos, não mostrarei fotos. E se appContext não for inicializado? A lógica de negócios desse método suporta isso. Se a mesma lógica for mais rigorosa, o lançamento de uma exceção faz parte da lógica de negócios e a verificação explícita de nulo deve ser usada (caso 3). A nova API Java Null-Safe se encaixa melhor aqui para especificar seletivamente o que implica e o que não implica que seja inicializado para ser à prova de falhas em caso de erros do programador.
Q. Código redundante pode ser executado e recursos desnecessários podem ser capturados.
R. Pode ocorrer se
getPhotoByName()
tentar abrir uma conexão com o banco de dados, criarPreparedStatement
e usar o nome da pessoa como um parâmetro SQL finalmente. A abordagem para uma pergunta desconhecida fornece uma resposta desconhecida (caso 1) funciona aqui. Antes de pegar recursos, o método deve verificar os parâmetros e retornar o resultado 'desconhecido', se necessário.Q. Essa abordagem tem uma penalidade de desempenho devido à abertura de tentativa de fechamento.
R. O software deve ser fácil de entender e modificar em primeiro lugar. Somente depois disso, é possível pensar em desempenho, e somente se necessário! e onde for necessário! ( fonte ) e muitos outros).
PS. Essa abordagem será tão razoável quanto o código de tratamento de erros separado do princípio de código "regular" for razoável em algum lugar. Considere o próximo exemplo:
PPS. Para aqueles que votam com menos votos (e não são tão rápidos em ler a documentação), gostaria de dizer que nunca vi uma exceção de ponteiro nulo (NPE) na minha vida. Mas essa possibilidade foi projetada intencionalmente pelos criadores de Java porque o NPE é uma subclasse de
Exception
. Temos um precedente na história Java quandoThreadDeath
é umError
não porque é realmente um erro de aplicação, mas apenas porque não tinha a intenção de ser pego! Quanto NPE se encaixa para ser umError
queThreadDeath
! Mas não é.Marque 'Sem dados' apenas se a lógica de negócios implicar.
e
Se appContext ou dataSource não for inicializado, o tempo de execução sem tratamento NullPointerException eliminará o encadeamento atual e será processado por Thread.defaultUncaughtExceptionHandler (para definir e usar seu criador de logs favorito ou outro mecanismo de notificação). Se não estiver definido, o ThreadGroup # uncaughtException imprimirá o rastreamento de pilha para o erro do sistema. Deve-se monitorar o log de erros do aplicativo e abrir o problema do Jira para cada exceção não tratada, que de fato é um erro do aplicativo. O programador deve corrigir o bug em algum lugar do material de inicialização.
fonte
NullPointerException
e o retornonull
são horríveis para depuração. Você acaba com o NPE mais tarde, e é realmente difícil descobrir o que era originalmente nulo.if (maybeNull.hasValue()) {...}
qual é a diferençaif (maybeNull != null)) {...}
?Maybe<T>
ouOptional<T>
não está no caso em que o seuT
pode ser nulo, mas no caso em que nunca deve ser nulo. Se você possui um tipo que significa explicitamente "esse valor pode ser nulo - use com cautela" e usa e retorna esse tipo de forma consistente, sempre que vir umT
código antigo simples no seu código, poderá assumir que ele nunca é nulo. (Claro, isso seria muito mais útil se executória pelo compilador.)O Java 7 tem uma nova
java.util.Objects
classe de utilitário na qual existe umrequireNonNull()
método. Tudo o que isso faz é lançar aNullPointerException
se seu argumento for nulo, mas ele limpará um pouco o código. Exemplo:O método é mais útil para verificar imediatamente antes de uma atribuição em um construtor, em que cada uso pode salvar três linhas de código:
torna-se
fonte
doCalc(someObject)
.doCalc()
, e ele não lança imediatamente o NPE quando recebe um valor nulo, você precisa verificar se há nulo e jogar o NPE você mesmo. É para isso queObjects.requireNonNull()
serve.Por fim, a única maneira de resolver completamente esse problema é usando uma linguagem de programação diferente:
nil
, e absolutamente nada acontecerá. Isso torna a maioria das verificações nulas desnecessárias, mas pode dificultar o diagnóstico de erros.fonte
"Problema" comum em Java, de fato.
Primeiro, meus pensamentos sobre isso:
Considero que é ruim "comer" alguma coisa quando NULL foi passado onde NULL não é um valor válido. Se você não está saindo do método com algum tipo de erro, significa que nada deu errado no seu método, o que não é verdade. Então você provavelmente retorna nulo nesse caso, e no método de recebimento verifica novamente nulo, e nunca termina, e você termina com "se! = Nulo", etc.
Portanto, IMHO, null deve ser um erro crítico que impede a execução adicional (ou seja, onde null não é um valor válido).
O jeito que eu resolvo esse problema é o seguinte:
Primeiro, sigo esta convenção:
E finalmente, no código, a primeira linha do método público é assim:
Observe que addParam () retorna self, para que você possa adicionar mais parâmetros para verificar.
O método
validate()
lançará verificadoValidationException
se algum dos parâmetros for nulo (marcado ou desmarcado é mais um problema de design / sabor, mas o meuValidationException
está marcado).A mensagem conterá o seguinte texto se, por exemplo, "planos" for nulo:
" O valor ilegal do argumento nulo é encontrado para o parâmetro [planos] "
Como você pode ver, o segundo valor no método addParam () (string) é necessário para a mensagem do usuário, porque você não pode detectar facilmente o nome da variável passada, mesmo com reflexão (mesmo que não seja o assunto desta postagem ...).
E sim, sabemos que além dessa linha, não encontraremos mais um valor nulo; portanto, apenas invocamos métodos com segurança nesses objetos.
Dessa forma, o código é limpo, fácil de manter e legível.
fonte
Ao fazer essa pergunta, você pode estar interessado em estratégias de tratamento de erros. O arquiteto da sua equipe deve decidir como trabalhar os erros. Existem várias maneiras de fazer isso:
permita que as exceções se propagem - capture-as no 'loop principal' ou em alguma outra rotina de gerenciamento.
Claro, também dê uma olhada na Programação Orientada a Aspectos - eles têm maneiras legais de inserir
if( o == null ) handleNull()
seu código de bytes.fonte
Além de usar,
assert
você pode usar o seguinte:Isso é um pouco melhor que:
fonte
if (!something) { x(); } else { y(); }
, estaria inclinado a refatorá-lo comoif (something) { y(); } else { x(); }
(embora se possa argumentar que essa!= null
é a opção mais positiva ...). Mais importante, porém, a parte importante do código não está envolvida em se{}
você tem um nível a menos de indentação na maior parte do método. Não sei se esse foi o raciocínio de fastcodejava, mas seria o meu.Apenas nunca use null. Não permita.
Nas minhas classes, a maioria dos campos e variáveis locais têm valores padrão não nulos e eu adiciono instruções de contrato (sempre ativadas) em todo o código para garantir que isso esteja sendo aplicado (já que é mais sucinto e mais expressivo do que permitir) aparecer como um NPE e depois resolver o número da linha etc.).
Depois de adotar essa prática, notei que os problemas pareciam se resolver. Você capturava as coisas muito mais cedo no processo de desenvolvimento por acidente e percebia que tinha um ponto fraco ... e mais importante .. ajuda a encapsular as preocupações dos diferentes módulos, diferentes módulos podem 'confiar' um no outro e não mais código com
if = null else
construções!Essa é uma programação defensiva e resulta em um código muito mais limpo a longo prazo. Sempre desinfete os dados, por exemplo, aqui, aplicando padrões rígidos, e os problemas desaparecem.
Os contratos são como mini-testes de unidade que estão sempre em execução, mesmo em produção, e quando as coisas falham, você sabe o porquê, em vez de um NPE aleatório, você precisa descobrir de alguma forma.
fonte
Guava, uma biblioteca principal muito útil do Google, possui uma API agradável e útil para evitar nulos. Acho UsingAndAvoidingNullExplained muito útil.
Conforme explicado no wiki:
Uso:
fonte
Esse é um problema muito comum para todos os desenvolvedores Java. Portanto, há suporte oficial no Java 8 para resolver esses problemas sem código desordenado.
O Java 8 foi introduzido
java.util.Optional<T>
. É um contêiner que pode ou não conter um valor não nulo. O Java 8 forneceu uma maneira mais segura de manipular um objeto cujo valor pode ser nulo em alguns casos. É inspirado nas idéias de Haskell e Scala .Em poucas palavras, a classe Opcional inclui métodos para lidar explicitamente com os casos em que um valor está presente ou ausente. No entanto, a vantagem comparada às referências nulas é que a classe Opcional <T> força você a pensar no caso em que o valor não está presente. Como conseqüência, você pode evitar exceções não desejadas de ponteiro nulo.
No exemplo acima, temos uma fábrica de serviços domésticos que retorna um identificador para vários aparelhos disponíveis em casa. Mas esses serviços podem ou não estar disponíveis / funcionais; isso significa que pode resultar em uma NullPointerException. Em vez de adicionar um valor nulo
if
condição antes de usar qualquer serviço, envolva-a no <Serviço> Opcional.ENVOLVER PARA A OPÇÃO <T>
Vamos considerar um método para obter uma referência de um serviço de uma fábrica. Em vez de retornar a referência de serviço, envolva-a com Opcional. Permite que o usuário da API saiba que o serviço retornado pode ou não estar disponível / funcional, usar defensivamente
Como você vê,
Optional.ofNullable()
fornece uma maneira fácil de envolver a referência. Existem outras maneiras de obter a referência de Opcional,Optional.empty()
&Optional.of()
. Um para retornar um objeto vazio em vez de ajustar novamente nulo e o outro para quebrar um objeto não nulo, respectivamente.ASSIM COMO EXATAMENTE AJUDA A EVITAR UMA VERIFICAÇÃO NULA?
Depois de agrupar um objeto de referência, o Opcional fornece muitos métodos úteis para chamar métodos em uma referência agrupada sem o NPE.
Optional.ifPresent chama o Consumidor especificado com uma referência, se for um valor não nulo. Caso contrário, não faz nada.
Representa uma operação que aceita um único argumento de entrada e não retorna nenhum resultado. Diferentemente da maioria das outras interfaces funcionais, o Consumer deve operar por meio de efeitos colaterais. É tão limpo e fácil de entender. No exemplo de código acima,
HomeService.switchOn(Service)
é invocado se a referência de retenção Opcional for não nula.Usamos o operador ternário frequentemente para verificar a condição nula e retornar um valor alternativo ou valor padrão. Opcional fornece outra maneira de lidar com a mesma condição sem verificar nulo. Optional.orElse (defaultObj) retorna defaultObj se o Opcional tiver um valor nulo. Vamos usar isso em nosso código de exemplo:
Agora HomeServices.get () faz a mesma coisa, mas de uma maneira melhor. Ele verifica se o serviço já foi inicializado ou não. Se for, retorne o mesmo ou crie um novo serviço Novo. <T> .orElse (T) opcional ajuda a retornar um valor padrão.
Finalmente, aqui está o nosso NPE, bem como o código nulo de verificação gratuita:
A publicação completa é NPE e também código nulo para verificação de cheques ... Sério? .
fonte
if(homeServices != null) {
que pode ser alterado parahomeServices.ifPresent(h -> //action)
;Eu gosto de artigos de Nat Pryce. Aqui estão os links:
Nos artigos, há também um link para um repositório Git para um Java Maybe Type que eu acho interessante, mas não acho que isso possa diminuir o inchaço do código de verificação. Depois de fazer algumas pesquisas na Internet, acho que ! = Inchaço de código nulo pode ser diminuído principalmente por um design cuidadoso.
fonte
Eu tentei o
NullObjectPattern
mas para mim nem sempre é o melhor caminho a percorrer. Às vezes, quando uma "não ação" não é apropriada.NullPointerException
é uma exceção de tempo de execução, que significa falha dos desenvolvedores e, com experiência suficiente, informa exatamente onde está o erro.Agora a resposta:
Tente tornar todos os seus atributos e seus acessadores o mais privado possível ou evite expô-los aos clientes. Você pode ter os valores do argumento no construtor, é claro, mas reduzindo o escopo, você não deixa a classe cliente passar um valor inválido. Se você precisar modificar os valores, sempre poderá criar um novo
object
. Você verifica os valores no construtor apenas uma vez e, no restante dos métodos, pode ter quase certeza de que os valores não são nulos.Obviamente, a experiência é a melhor maneira de entender e aplicar essa sugestão.
Byte!
fonte
Provavelmente, a melhor alternativa para o Java 8 ou mais recente é usar a
Optional
classeIsso é especialmente útil para longas cadeias de possíveis valores nulos. Exemplo:
Exemplo sobre como lançar exceção em null:
O Java 7 introduziu o
Objects.requireNonNull
método que pode ser útil quando algo deve ser verificado quanto à não-nulidade. Exemplo:fonte
Posso responder de maneira mais geral!
Nós geralmente enfrentam esse problema quando os métodos de obter os parâmetros na forma como não se espera (mau chamada de método é culpa do programador). Por exemplo: você espera obter um objeto, em vez disso, obtém um nulo. Você espera obter uma String com pelo menos um caractere, em vez de uma String vazia ...
Portanto, não há diferença entre:
}
ou
Ambos querem ter certeza de que recebemos parâmetros válidos antes de executar outras funções.
Conforme mencionado em algumas outras respostas, para evitar os problemas acima, você pode seguir o padrão Design por contrato . Por favor, consulte http://en.wikipedia.org/wiki/Design_by_contract .
Para implementar esse padrão em java, você pode usar anotações básicas de java como javax.annotation.NotNull ou usar bibliotecas mais sofisticadas como o Hibernate Validator .
Apenas uma amostra:
Agora você pode desenvolver com segurança a função principal do seu método sem precisar verificar os parâmetros de entrada, pois eles protegem seus métodos de parâmetros inesperados.
Você pode dar um passo adiante e garantir que apenas pojos válidos possam ser criados no seu aplicativo. (amostra do site do validador de hibernação)
fonte
javax
, por definição, não é "Java principal".Eu ignoro as respostas que sugerem o uso de objetos nulos em todas as situações. Esse padrão pode quebrar o contrato e enterrar os problemas cada vez mais fundo, em vez de resolvê-los, sem mencionar que o uso inadequado criará outra pilha de código padrão que exigirá manutenção futura.
Na realidade, se algo retornado de um método puder ser nulo e o código de chamada tiver que tomar uma decisão sobre isso, deve haver uma chamada anterior que garanta o estado.
Lembre-se também de que esse padrão de objeto nulo terá falta de memória se usado sem cuidado. Para isso - a instância de um NullObject deve ser compartilhada entre proprietários, e não uma instância de unigue para cada um deles.
Também não recomendaria usar esse padrão onde o tipo deve ser uma representação de tipo primitiva - como entidades matemáticas, que não são escalares: vetores, matrizes, números complexos e objetos POD (Plain Old Data), que devem conter o estado na forma de tipos internos Java. No último caso, você acabaria chamando métodos getter com resultados arbitrários. Por exemplo, o que um método NullPerson.getName () retornará?
Vale a pena considerar esses casos para evitar resultados absurdos.
fonte
Faça isso em seu próprio código e você poderá evitar verificações! = Null.
Na maioria das vezes, as verificações nulas parecem proteger os loops de coleções ou matrizes; portanto, basta inicializá-las vazias, pois você não precisará de verificações nulas.
Há uma pequena sobrecarga nisso, mas vale a pena por código mais limpo e menos NullPointerExceptions.
fonte
Este é o erro mais comum ocorrido para a maioria dos desenvolvedores.
Temos várias maneiras de lidar com isso.
Abordagem 1:
notNull (objeto Objeto, mensagem String)
Abordagem 2:
Abordagem 3:
Abordagem 4:
fonte
fonte
ObjectUtils.defaultIfNull()
. Há uma mais geral:ObjectUtils.firstNonNull()
que pode ser usado para implementar uma estratégia degradante:firstNonNull(bestChoice, secondBest, thirdBest, fallBack);