Perché una variabile "Class" non può essere passata a instanceof?


89

Perché questo codice non viene compilato?

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

Perché non riesco a passare una variabile di classe a instanceof?

Risposte:


131

L' instanceofoperatore lavora sui tipi di riferimento, come Integer, e non sugli oggetti, come new Integer(213). Probabilmente vuoi qualcosa di simile

clazz.isInstance(obj)

Nota a margine: il tuo codice sarà più conciso se scrivi

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

Tuttavia, non sono più sicuro di aver bisogno di un metodo.


So che il codice è totalmente inutile, voglio solo dimostrare la mia confusione :)
eric2323223

6
Integernon è un letterale di classe. Integer.classsarebbe un letterale di classe (vedere § 15.8.2 del JLS: java.sun.com/docs/books/jls/third_edition/html/… ). L' instanceofoperatore accetta un "ReferenceType" (aka un nome di tipo) come specificato § 15.20.2 del JLS: java.sun.com/docs/books/jls/third_edition/html/…
Joachim Sauer

3
Lo userei clazz.isInstance(obj)poiché l'oggetto è già stato fornito.
Donal Fellows

13

instanceofpuò essere utilizzato solo con nomi di classi espliciti (dichiarati in fase di compilazione). Per eseguire un controllo di runtime , dovresti fare:

clazz.isInstance(obj)

Questo ha un piccolo vantaggio in clazz.isAssignableFrom(..)quanto gestisce obj == nullmeglio il caso .


5

Come altri hanno già detto, non puoi passare una variabile di classe a instanceofperché una variabile di classe fa riferimento a un'istanza di un oggetto , mentre la mano destra di instanceofdeve essere un tipo . Cioè, instanceofnon significa "y è un'istanza di Object x", significa "y è un'istanza di tipo X". Se non conosci la differenza tra un oggetto e un tipo, considera:

Object o = new Object();

In questo caso, il tipo è Objected oè un riferimento all'istanza dell'oggetto Object con quel tipo. Quindi:

if(o instanceof Object)

è valido ma

if(o instanceof o)

non è perché osul lato destro c'è un oggetto, non un tipo.

Più specifico per il tuo caso, un'istanza di classe non è un tipo, è un oggetto (che viene creato per te dalla JVM). Nel tuo metodo, Classè un tipo, ma clazzè un oggetto (beh, un riferimento a un oggetto)

Ciò di cui hai bisogno è un modo per confrontare un oggetto con un oggetto classe. Si scopre che questo è popolare quindi questo è fornito come un metodo dell'oggetto Classe: isInstance().

Ecco il Java Doc per isInstance, che lo spiega meglio:

public boolean isInstance(Object obj)

Determina se l'oggetto specificato è compatibile con l'assegnazione con l'oggetto rappresentato da questa classe. Questo metodo è l'equivalente dinamico dell'operatore instanceof del linguaggio Java. Il metodo restituisce true se l'argomento Object specificato non è null e può essere eseguito il cast al tipo di riferimento rappresentato da questo oggetto Class senza generare un'eccezione ClassCastException. In caso contrario, restituisce false.

In particolare, se questo oggetto Class rappresenta una classe dichiarata, questo metodo restituisce true se l'argomento Object specificato è un'istanza della classe rappresentata (o di una delle sue sottoclassi); altrimenti restituisce false. Se questo oggetto Class rappresenta una classe array, questo metodo restituisce true se l'argomento Object specificato può essere convertito in un oggetto della classe array mediante una conversione di identità o una conversione di riferimento di ampliamento; altrimenti restituisce false. Se questo oggetto Class rappresenta un'interfaccia, questo metodo restituisce true se la classe o qualsiasi superclasse dell'argomento Object specificato implementa questa interfaccia; altrimenti restituisce false. Se questo oggetto Class rappresenta un tipo primitivo, questo metodo restituisce false.

Parametri: obj - l'oggetto da controllare
Restituisce: true se obj è un'istanza di questa classe
Da: JDK1.1


3

In primo luogo, instanceofrichiede che l'operando a destra sia una classe effettiva (ad esempio obj instanceof Objector obj instanceof Integer) e non una variabile di tipo Class. In secondo luogo, hai commesso un errore principiante abbastanza comune che davvero non dovresti fare ... il seguente schema:

if ( espressione_condizionale ) {
    restituire vero;
} altro{
    return false;
}

Quanto sopra può essere modificato in:

return conditional_expression ;

Dovresti sempre eseguire quel refactoring, poiché elimina un'istruzione if ... else ridondante. Allo stesso modo, l'espressione può essere rifattorizzata allo stesso risultato.return conditional_expression ? true : false;


2
Non è un errore. Forse goffo ma totale ok. Forse vuoi un codice aggiuntivo prima di tornare nel prossimo futuro ...
L'incredibile
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.