Une vérification nulle est-elle nécessaire avant d'appeler instanceof?

1354

Est-ce que null instanceof SomeClassretourner falseou de jeter un NullPointerException?

Johan Lübcke
la source
Il est également `` important '' ou au moins très utile comme ligne de départ (ou très tôt) de `` meilleure pratique '' pour toute comparaison ou égal ou méthode similaire conçue pour réussir uniquement sur des objets non nuls du même type, et vous protège contre les «cas idiots» en une seule ligne. moins de code = moins de bugs.
13
Pour peser sur le "est-ce utile?" débat - je n'ai jamais écrit mon propre code Java (donc je ne sais pas facilement où sont les spécifications, et la compilation d'un test serait très simple), mais je suis en train de convertir manuellement Java en JavaScript. Mon code échouait sur une référence nulle, et la recherche sur Google m'a permis de voir la réponse acceptée, qui a confirmé qu'il s'agissait d'un comportement attendu et que je manquais une vérification nulle implicite. Très utile, dans mon cas.
Scott Mermelstein

Réponses:

1839

Non, une vérification nulle n'est pas nécessaire avant d'utiliser instanceof.

L'expression x instanceof SomeClassest falsesi xest null.

Dans la spécification du langage Java, section 15.20.2, «Opérateur de comparaison de type instanceof» :

"Au moment de l'exécution, le résultat de l' instanceofopérateur est truesi la valeur de RelationalExpression ne l'est pasnull et que la référence peut être convertie en ReferenceType sans augmenter a ClassCastException. Sinon, le résultat est false."

Donc, si l'opérande est nul, le résultat est faux.

Andy Thomas
la source
377
Cette réponse est plus correcte que try itparce que le comportement actuel n'est pas le même que le comportement garanti .
Luke
3
Cette question entre en jeu lors du chapitre de Joshua Bloch sur l'égalité des objets dans Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
Kevin Meredith
17
Plus précisément, au point 8, il note que dans les méthodes equals (), un opérateur instanceof sert à deux fins - il vérifie que l'argument est à la fois non nul et de type correct. "... [S] o vous n'avez pas besoin d'une vérification nulle distincte."
Andy Thomas
2
@BenThurley - L' instanceofopérateur de Java faisait partie de Java 1.0, sorti il ​​y a près de 20 ans. Il est peu probable de changer le comportement d'une manière qui briserait le code existant, en l'absence d'un avantage qui l'emporte sur cet énorme coût. Il y a vingt ans, il aurait peut-être pu y avoir des arguments pour renvoyer true si l'argument pouvait être casté, ou lever une exception pour un argument nul. Mais ces définitions auraient nécessité des vérifications nulles distinctes.
Andy Thomas
3
@BenThurley - Le comportement est garanti par les spécifications Java passées et présentes. Je pense que le point de Luke traite des limites de l'expérimentation dans la détermination du comportement garanti du présent.
Andy Thomas
267

Utilisation d'une référence nulle comme premier opérande à instanceofrenvoyer false.

Bozho
la source
268
(Et maintenant, il faut 10 secondes pour trouver cette question dans Google)
PL_kolek
73

Très bonne question en effet. J'ai juste essayé pour moi.

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));
    }
}

Impressions

true
true
false
false

JLS / 15.20.2. Opérateur de comparaison de type instanceof

Au moment de l'exécution, le résultat de l' instanceofopérateur est truesi la valeur de RelationalExpression ne l'est pas nullet que la référence peut être convertie en ReferenceType sans augmenter a ClassCastException. Sinon, le résultat est false.

API / classe # isInstance (objet)

Si cet Classobjet représente une interface, cette méthode renvoie truesi la classe ou toute superclasse de l' Objectargument spécifié implémente cette interface; il revient falsesinon. Si cet Classobjet représente un type primitif, cette méthode retourne false.

Jin Kwon
la source
Un peu déroutant. s est une chaîne car elle dit "chaîne s", s n'est pas une chaîne car elle est nulle. Alors c'est quoi ce bordel?
Kai Wang
1
@KaiWang sn'est qu'une variable de référence d'objet. Il peut faire référence à un objet réellement existant ( "") ou à une nullréférence littérale.
Jin Kwon
Je suis encore confus. s peut être maintenant nul, mais il ne peut être pointé que vers une instance de String plus tard. Il ne peut pas être signalé, comme un entier. Il s'agit donc toujours d'une sorte de chaîne, même si elle est nulle. Ça n'a pas beaucoup de sens ...
Kai Wang
@KaiWang Vous confondez le type de variable avec le type de l'objet réel. Les variables ne sont pas des instances; ce ne sont en fait que des pointeurs. nulln'est pas une donnée de chaîne, quelle que soit la variable qui la pointe. s instanceof Stringn'est pas le même que field.getType().equals(String.class), par exemple.
Matthieu lu
@KaiWang, vous devez imaginer que dans l'appel, s instanceof Stringle sest remplacé par la valeur réelle, ce qui deviendrait "" instanceof Stringet null instanceof String. Penser à cela comme cela peut avoir plus de sens.
Timo Türschmann
24

Non ce n'est pas. instanceofretournerait falsesi son premier opérande est null.

RoflcoptrException
la source
16

Tout comme une friandise :

Même reviendra .(((A)null)instanceof A)false


(Si le transtypage nullsemble surprenant, vous devez parfois le faire, par exemple dans des situations comme celle-ci:

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).
  }
}

Ainsi Test.test((A)null)imprimera a instanceof A: false.)


PS: Si vous embauchez, veuillez ne pas l'utiliser comme une question d'entretien d'embauche. :RÉ

Attila Tanyi
la source
7

Non . Le littéral Java nulln'est une instance d'aucune classe. Par conséquent, il ne peut être une instance d' aucune classe. instanceof retournera soit falseoutrue donc les <referenceVariable> instanceof <SomeClass>retours falselorsque la referenceVariablevaleur est nulle.

Développeur Marius Žilėnas
la source
5
Cette explication semble étrangement circulaire ... mais je sais ce que vous voulez dire :-)
Kris
@Kris ty pour le commentaire J'ai compris ce que tu veux dire :). Modifié un peu la réponse :).
Développeur Marius Žilėnas
1

L' instanceofopérateur n'a pas besoin de nullvérifications explicites , car il ne lance pas de a NullPointerExceptionsi l'opérande l'est null.

Au moment de l'exécution, le résultat de l' instanceofopérateur est vrai si la valeur de l'expression relationnelle ne l'est pas nullet que la référence peut être convertie en type de référence sans déclencher une exception de conversion de classe.

Si l'opérande l'est null, l' instanceofopérateur retourne falseet par conséquent, des vérifications null explicites ne sont pas requises.

Considérez l'exemple ci-dessous,

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");
         }
}

L'utilisation correcte de instanceofest comme indiqué ci-dessous,

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
la source