Java: Como verificar se o objeto é nulo?

87

Estou criando um aplicativo que recupera imagens da web. Caso a imagem não possa ser recuperada, outra imagem local deve ser usada.

Ao tentar executar as seguintes linhas:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

A linha if (drawable.equals (null)) lança uma exceção se drawable for nulo.

Alguém sabe como o valor de drawable deve ser verificado para não lançar uma exceção caso seja nulo e recuperar a imagem local (execute drawable = getRandomDrawable ())?

Niko Gamulin
fonte
23
Use if (drawable == null) Chamar qualquer método em um objeto NULL é um NullPointerException.
diciu
3
Por que você não escreve uma resposta usual em vez de um comentário, diciu?
deamon
@JaredBurrows Não edite o código em uma pergunta de uma forma que anule o propósito da pergunta!
Gilles 'SO- pare de ser mal'
@Gilles Leia meu comentário editorial, tornei o código mais legível.
Jared Burrows de
@JaredBurrows Não, sua edição não foi uma mudança de “formatação”. Você alterou o código que não funcionava, que era o objeto da questão, para um código funcional que tornava a questão discutível.
Gilles 'SO- pare de ser mal'

Respostas:

35

Solução Java 8 editada:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Você pode declarar drawable finalneste caso.

Como Chasmo apontou, o Android não oferece suporte a Java 8 no momento. Portanto, essa solução só é possível em outros contextos.

deamon
fonte
7
Provavelmente não é uma boa ideia - você está voltando para o Fortran 60, onde ambos os lados da condicional são avaliados e, em seguida, apenas um é usado. Isso é ruim se o ramo não usado tiver qualquer cálculo, o que é verdadeiro na maioria das vezes, portanto, não é um método geralmente útil. Eu moveria a condição para a Commonclasse e permitiria que você fornecesse um URL substituto e manteria as responsabilidades juntas.
Pete Kirkham
1
O exemplo agora foi completamente reescrito em Java 8, então minha solução não sofre mais de avaliações inúteis (como @PeteKirkham apontou em minha solução original).
deamon
1
Android não suporta Java 8. Ele só suporta até Java 7 (se você tiver kitkat) e ainda não tem invokedynamic, apenas o novo açúcar de sintaxe. Além disso, Optional.ofimplica que o valor não é nulo e, portanto, orElseGeté desnecessário. Você deve usar Optional.ofNullableneste caso.
Martin Seeler
179
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

O equals()método verifica a igualdade de valor , o que significa que ele compara o conteúdo de dois objetos. Como nullnão é um objeto, isso falha ao tentar comparar o conteúdo do seu objeto com o conteúdo de null.

O ==operador verifica a igualdade de referência , o que significa que verifica se os dois objetos são realmente o mesmo objeto . Isso não exige que os objetos realmente existam; dois objetos inexistentes ( nullreferências) também são iguais.

Thomas
fonte
56
Quero adicionar uma dica muito valiosa: se você tiver strings ou constantes para comparar, sempre coloque-as primeiro na cláusula equals. (if ("coyote" .equals (myDogString))) é muito melhor do que (if (myDogString.equals ("coyote"))) porque no segundo caso myDogString pode ser nulo e lança um NPE, enquanto no primeiro caso não não importa se myDogString for nulo.
Thorsten S.
20
Conhecida como condição Yoda: "se for um coiote, o cachorro é ..."
Thomas
1
Eu também gostaria de acrescentar que, como o Java 7 existe um método Objects.equals (), isso permite que você não se importe com a sintaxe do Yoda
maryokhin
21

Eu uso esta abordagem:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

Desta forma, descobri que melhora a legibilidade da linha - conforme leio rapidamente um arquivo de origem, posso ver que é uma verificação nula.

Com relação ao motivo pelo qual você não pode chamar .equals()um objeto que pode ser null; se a referência de objeto que você tem (ou seja, 'drawable') é de fato null, ela não aponta para um objeto na pilha. Isso significa que não há nenhum objeto no heap no qual a chamada para equals()possa ser bem-sucedida.

Boa sorte!

sem café
fonte
4
Eu também prefiro a construção if (<constant> == <variable>) como uma forma de me proteger de atribuição acidental.
Scott
8

faça você mesmo

private boolean isNull(Object obj) {
    return obj == null;
}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (isNull(drawable)) {
    drawable = getRandomDrawable();
}
Eddie B
fonte
6
drawable.equals(null)

A linha acima chama o método "equals (...)" no objeto drawable.

Então, quando drawable não é nulo e é um objeto real, tudo vai bem, pois chamar o método "equals (null)" retornará "false"

Mas quando "drawable" é nulo, isso significa chamar o método "equals (...)" em um objeto nulo, significa chamar um método em um objeto que não existe, por isso lança "NullPointerException"

Para verificar se um objeto existe e não é nulo, use o seguinte

if(drawable == null) {
    ...
    ...
}

Na condição acima, estamos verificando se a variável de referência "drawable" é nula ou contém algum valor (referência a seu objeto), portanto, não lançará uma exceção no caso de drawable ser nulo como verificação

null == null

é válido.

Yatendra Goel
fonte
5

if (yourObject instanceof yourClassName)irá avaliar falsese yourObjecté null.

heapuser
fonte
0

Provavelmente é um pouco mais eficiente capturar um NullPointerException. Os métodos acima significam que o tempo de execução está verificando ponteiros nulos duas vezes.

Ao Sr
fonte
1
Onde está a if x == nullsolução de check-in duplo ?
deamon
Após a instrução if, o tempo de execução verificará novamente se há um ponteiro nulo quando o objeto for usado. Não sei se isso é otimizado ou não pelo compilador, no entanto.
Tom R de
4
Isso vai contra a sabedoria convencional, usando exceções como fluxo de controle.
James
1
As exceções são muito caras, pois precisam criar um rastreamento de pilha inteiro.
deamon
0

Use google guava libs para lidar com is-null-check (atualização do deamon)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());
Bala
fonte
É melhor usar o Java 8 Optionalhoje.
deamon
-1

Só para dar algumas idéias ao desenvolvedor de código Java do oracle :-)

A solução já existe em .Net e é muito mais legível!

Em Visual Basic .Net

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

Em C #

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

Essas soluções são poderosas como solução Java opcional (a string padrão só é avaliada se o valor original for nulo) sem usar a expressão lambda, apenas ao adicionar um novo operador.

Apenas para ver rapidamente a diferença com a solução Java, adicionei as 2 soluções Java

Usando opcional em Java

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Usando {} em Java

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

Pessoalmente, gosto de VB.Net mas prefiro ?? C#ou if {}solução em Java ... e você?

Schlebe
fonte