È 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.