A verificação nula é necessária antes de chamar instanceof?

1354

Irá null instanceof SomeClassretornar falseou jogar um NullPointerException?

Johan Lübcke
fonte
Também é 'importante' ou pelo menos muito útil como uma linha inicial (ou muito cedo) de 'melhor prática' para qualquer método Compare ou Igual ou similar que foi projetado para ter êxito apenas em objetos não nulos do mesmo tipo e protege você contra os 'casos bobos' em uma única linha. menos código = menos bugs.
13
Pesar o "isso é útil?" debate - Eu nunca escrevi meu próprio código Java (portanto, não sei onde estão as especificações, e compilar um teste não seria nada trivial), mas atualmente estou convertendo manualmente Java para JavaScript. Meu código falhou em uma referência nula e, pesquisando isso no Google, deixe-me ver a resposta aceita, que confirmou que era um comportamento esperado e que estava faltando uma verificação nula implícita. Muito útil, no meu caso.
27413 Scott Mermelstein

Respostas:

1839

Não, uma verificação nula não é necessária antes de usar instanceof.

A expressão x instanceof SomeClassé falsesex énull .

Na Especificação da linguagem Java, seção 15.20.2, "Digite operador de comparação de instância" :

"No tempo de execução, o resultado do instanceofoperador é truese o valor da RelationalExpression não fornull e a referência puder ser convertida no ReferenceType sem gerar a ClassCastException. Caso contrário, o resultado será false."

Portanto, se o operando for nulo, o resultado será falso.

Andy Thomas
fonte
377
Essa resposta é mais correta do que try itporque o comportamento atual não é o mesmo que o comportamento garantido .
Lucas
3
Esta questão entra em jogo durante o capítulo de Joshua Bloch sobre a igualdade de objeto Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
Kevin Meredith
17
Especificamente, no Item 8, ele observa que, nos métodos equals (), uma instância de operador serve a dois propósitos - verifica se o argumento é não nulo e do tipo correto. "... Então você não precisa de uma verificação nula separada."
Andy Thomas
2
@BenThurley - O instanceofoperador do Java fazia parte do Java 1.0, lançado há quase 20 anos. É improvável mudar o comportamento agora de uma maneira que interrompa o código existente, sem alguns benefícios que superem esse enorme custo. Vinte anos atrás, talvez houvesse argumentos para retornar true se o argumento pudesse ser lançado ou lançar uma exceção para um argumento nulo. Mas essas definições teriam exigido verificações nulas separadas.
Andy Thomas
3
@ BenThurley - O comportamento é garantido pelas especificações Java passadas e presentes. Acho que o argumento de Luke aborda as limitações da experimentação na determinação do comportamento garantido do presente.
Andy Thomas
267

Utilizando uma referência nula como o primeiro operando a instanceofretornar false.

Bozho
fonte
268
(E agora leva 10 segundos para encontrar esta pergunta no Google)
PL_kolek
73

Muito boa pergunta, de fato. Eu apenas tentei por mim mesmo.

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

Impressões

true
true
false
false

JLS / 15.20.2. Operador de comparação de tipo instanceof

No tempo de execução, o resultado do instanceofoperador é truese o valor da RelationalExpression não for nulle a referência poderá ser convertida para o ReferenceType sem gerar a ClassCastException. Caso contrário, o resultado é false.

API / classe # isInstance (Object)

Se este Classobjeto representa uma interface, esse método retorna truese a classe ou qualquer superclasse do Objectargumento especificado implementa essa interface; retorna falsecaso contrário. Se este Classobjeto representar um tipo primitivo, esse método retornará false.

Jin Kwon
fonte
Meio confuso. s é uma String porque diz "String s", s não é uma String porque é nula. Então, o que diabos é s?
Kai Wang
1
@KaiWang sé apenas uma variável de referência de objeto. Ele pode se referir a um objeto realmente existente ( "") ou a uma nullreferência literal (a) .
Jin Kwon
Ainda estou confuso. s pode ser nulo agora, mas só pode ser apontado para uma instância String posteriormente. Não pode ser apontado como um número inteiro. Portanto, ainda é um tipo de String, mesmo que seja nulo. Apenas não faz muito sentido ...
Kai Wang
@KaiWang Você está confundindo o tipo de variável com o tipo do objeto real. Variáveis ​​não são instâncias; eles são efetivamente apenas indicadores. nullnão são dados de string, não importa qual variável esteja apontando para ele. s instanceof Stringnão é o mesmo que field.getType().equals(String.class), por exemplo.
Matthew Leia
@KaiWang, você deve imaginar que na chamada s instanceof Stringos valores ssão substituídos pelo valor real, para que se tornem "" instanceof Stringe null instanceof String. Pensar assim pode fazer mais sentido.
Timo Türschmann
24

Não, não é. instanceofretornaria falsese seu primeiro operando for null.

RoflcoptrException
fonte
16

Assim como um petisco :

Mesmo vai voltar .(((A)null)instanceof A)false


(Se a nullimpressão tipográfica parecer surpreendente, às vezes você precisará fazer isso, por exemplo, em situações como esta:

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

O mesmo Test.test((A)null)será impresso a instanceof A: false.)


PS: Se você estiver contratando, não use isso como uma pergunta de entrevista de emprego. : D

Attila Tanyi
fonte
7

Não . O literal Java nullnão é uma instância de nenhuma classe. Portanto, não pode ser uma instância de nenhuma classe. instanceof retornará um falseou,true portanto, o <referenceVariable> instanceof <SomeClass>retorno falsequando o referenceVariablevalor for nulo.

Desenvolvedor Marius Žilėnas
fonte
5
Isso soa explicação estranhamente circular ... mas eu sei que você quer dizer :-)
Kris
@ Kris Ty pelo comentário, eu entendi o que você quer dizer :). Editou uma resposta um pouco :).
Desenvolvedor Marius Žilėnas
1

O instanceofoperador não precisa de nullverificações explícitas , pois não lança a NullPointerExceptionse o operando estivernull .

No tempo de execução, o resultado do instanceofoperador é verdadeiro se o valor da expressão relacional não for nulle a referência puder ser convertida para o tipo de referência sem gerar uma exceção de conversão de classe.

Se o operando for null, o instanceofoperador retornará falsee, portanto, verificações nulas explícitas não serão necessárias.

Considere o exemplo abaixo,

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

O uso correto de instanceofé como mostrado abaixo,

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
Nikhil Kumar
fonte