È necessario il controllo null prima di chiamare instanceof?


1354

Sarà null instanceof SomeClasstornare falseo di gettare una NullPointerException?


È anche 'importante' o almeno molto utile come linea di partenza (o molto precoce) 'best practice' per qualsiasi metodo di confronto o uguale o simile progettato per avere successo solo su oggetti non nulli dello stesso tipo, e ti protegge dai "casi stupidi" in una sola riga. meno codice = meno bug.

13
Per valutare "è utile?" dibattito - Non ho mai scritto il mio codice Java (quindi non so facilmente dove sono le specifiche e compilare un test sarebbe molto banale), ma attualmente sto convertendo manualmente Java in JavaScript. Il mio codice non andava a buon fine su un riferimento null, e cercandolo su Google mi ha fatto vedere la risposta accettata, che ha confermato che si trattava di un comportamento previsto e che mancava un controllo null implicito. Molto utile, nel mio caso.
— Scott Mermelstein,

Risposte:


1839

No, non è necessario un controllo null prima di utilizzare instanceof.

L'espressione x instanceof SomeClassè falseif xis null.

Da Java Language Specification, sezione 15.20.2, "Tipo di confronto dell'istanza dell'operatore" :

"In fase di esecuzione, il risultato instanceofdell'operatore è truese il valore di RelationalExpression non lo ènull e il riferimento potrebbe essere trasmesso a ReferenceType senza aumentare a ClassCastException. Altrimenti il ​​risultato è false."

Quindi se l'operando è nullo, il risultato è falso.


377
Questa risposta è più corretta che try itperché il comportamento attuale non è lo stesso del comportamento garantito .
— Luca

3
Questa domanda entra in gioco durante il capitolo di Joshua Bloch sull'uguaglianza degli oggetti in Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
— Kevin Meredith,

17
Nello specifico, nell'articolo 8, osserva che nei metodi equals (), un'istanza dell'operatore ha due scopi: verifica che l'argomento sia sia non nullo sia del tipo corretto. "... [S] o non hai bisogno di un controllo null separato."
— Andy Thomas,

2
@BenThurley - L' instanceofoperatore Java faceva parte di Java 1.0, rilasciato circa 20 anni fa. Cambiare il comportamento ora in un modo che spezzerebbe il codice esistente è improbabile, in assenza di alcuni benefici che superano quell'enorme costo. Venti anni fa, forse ci potevano essere argomenti per restituire vero se l'argomento potesse essere lanciato, o lanciare un'eccezione per un argomento nullo. Ma tali definizioni avrebbero richiesto controlli nulli separati.
— Andy Thomas,

3
@BenThurley - Il comportamento è garantito dalle specifiche Java passate e presenti. Penso che il punto di Luke affronti i limiti della sperimentazione nel determinare il comportamento garantito del presente.
— Andy Thomas,

267

Utilizzo di un riferimento null come primo operando da instanceofrestituire false.


268
(E ora ci vogliono 10 secondi per trovare questa domanda su Google)
— PL_kolek,

73

Davvero un'ottima domanda. Ho appena provato per me stesso.

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

stampe

true
true
false
false

JLS / 15.20.2. Tipo di confronto Operatore instanceof

In fase di esecuzione, il risultato instanceofdell'operatore è truese il valore di RelationalExpression non lo è nulle il riferimento potrebbe essere trasmesso a ReferenceType senza aumentare a ClassCastException. Altrimenti il ​​risultato è false.

API / Class # isInstance (Object)

Se questo Classoggetto rappresenta un'interfaccia, questo metodo restituisce truese la classe o qualsiasi superclasse Objectdell'argomento specificato implementa questa interfaccia; ritorna falsealtrimenti. Se questo Classoggetto rappresenta un tipo primitivo, questo metodo restituisce false.


Un po 'confuso. s è una stringa perché dice "String s", s non è una stringa perché è nulla. Quindi che diavolo è s?
— Kai Wang,

1
@KaiWang sè solo una variabile di riferimento all'oggetto. Può fare riferimento a un oggetto ( "") effettivamente esistente o può fare riferimento a un nullriferimento letterale () .
— Jin Kwon,

Sono ancora confuso. s potrebbe essere nullo ora, ma può essere indirizzato a un'istanza String solo in seguito. Non può essere indicato come un numero intero. Quindi è ancora una specie di stringa, anche se è nulla. Semplicemente non ha molto senso ...
— Kai Wang,

@KaiWang Stai confondendo il tipo di variabile con il tipo dell'oggetto reale. Le variabili non sono istanze; sono effettivamente solo puntatori. nullnon sono dati stringa, indipendentemente dalla variabile che lo indica. s instanceof Stringnon è lo stesso field.getType().equals(String.class), ad esempio.
— Matteo Leggi il

@KaiWang si deve immaginare che nella chiamata s instanceof Stringalla sviene sostituito con il valore effettivo, in modo che sarebbe diventato "" instanceof Stringe null instanceof String. Pensarci in questo modo potrebbe avere più senso.
— Timo Türschmann,


16

Proprio come un bocconcino :

Anche tornerà .(((A)null)instanceof A)false


(Se il typecasting nullsembra sorprendente, a volte devi farlo, ad esempio in situazioni come questa:

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

Quindi Test.test((A)null)stamperà a instanceof A: false.)


PS: se stai assumendo, per favore non usarlo come domanda per un colloquio di lavoro. : D


7

No . Java Literal nullnon è un'istanza di nessuna classe. Pertanto non può essere un'istanza di nessuna classe. instanceof restituirà uno falseotrue quindi i <referenceVariable> instanceof <SomeClass>ritorni falsequando il referenceVariablevalore è null.


5
Questa spiegazione suona stranamente circolare ... ma so cosa intendi :-)
— Kris,

@Kris ty per il commento ho capito cosa intendi :). Modificato un po 'una risposta :).
— Sviluppatore Marius Žilėnas,

1

L' instanceofoperatore non ha bisogno di nullcontrolli espliciti , in quanto non genera un NullPointerExceptionse l'operando lo ènull .

In fase di esecuzione, il risultato instanceofdell'operatore è vero se il valore dell'espressione relazionale non lo ènull e il riferimento può essere trasmesso al tipo di riferimento senza sollevare un'eccezione di cast di classe.

Se l'operando è null, l' instanceofoperatore ritornafalse e quindi non sono richiesti controlli null espliciti.

Considera l'esempio seguente,

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'uso corretto di instanceofè come mostrato di seguito,

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");
         }  
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.