Come determinare la classe di un oggetto?


510

Se class Be class Cestendono class Ae ho un oggetto di tipo Bo C, come posso determinare di quale tipo è un'istanza?


14
@starblue Casting sarebbe la prima cosa che mi viene in mente. Dubito che l' istanza dell'operatore esisterebbe se non ce ne fosse bisogno.
b1nary.atr0phy,

@ b1nary.atr0phy non sarebbe bene usare prima l'operatore isntanceof. Se c'è un cast a un tipo incompatibile, io credo che si tradurrà in un ClassCastException
committedandroider

Risposte:


801
if (obj instanceof C) {
//your code
}

31
È utile notare il controllo inverso o come verificare se un oggetto NON è un'istanza di una classe:if(!(obj instanceof C))
Dzhuneyt

32
Credo che il metodo getClass () sia la risposta alla domanda originale. In questo caso (obj esempio di A) darebbe anche un output "vero", ma l'intento è quello di trovare la classe di runtime dell'oggetto nell'immagine. Se Parent1 è esteso da Child1 e Child2, provare il seguente code Child1 child1 = new Child1 (); Parent1 parentChild = new Child2 (); Child2 child2 = new Child2 (); (child1 istanza di Parent1); (child1 istanza di Child1); (istanza parentChildof Child2); (parentChild instanceof Parent1); (istanza parentChildof Child1); code , può chiarire l'intento di instanceof.
Bhavesh Agarwal,

Sicuramente un'alternativa alla costruzione di un'interfaccia
John Merlino,

3
Cosa succede se ho due classi che implementano un'unica interfaccia? Come distinguo la classe esatta dell'oggetto?
olyv

3
Una cosa però, non funziona se obj è null. La soluzione sarebbe quindi ParentInterface.class.isAssignableFrom (Child.class)
alexbt


178

Sono state presentate più risposte a destra, ma ci sono ancora più metodi: Class.isAssignableFrom()e semplicemente tentando di lanciare l'oggetto (che potrebbe lanciare a ClassCastException).

Modi possibili riassunti

Riassumiamo i modi possibili per verificare se un oggetto objè un'istanza di tipo C:

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

Differenze nella nullgestione

C'è una differenza nella nullgestione però:

  • Nei primi 2 metodi le espressioni valutano falseif objis null( nullnon è un'istanza di nulla).
  • Il terzo metodo avrebbe NullPointerExceptionovviamente lanciato .
  • Al contrario, il 4o e il 5o metodo accettano nullperché nullpossono essere lanciati su qualsiasi tipo!

Da ricordare: null non è un'istanza di alcun tipo ma può essere trasmessa a qualsiasi tipo.

Appunti

  • Class.getName()non dovrebbe essere usato per eseguire un test "is-instance-of" poiché l'oggetto non è di tipo Cma una sua sottoclasse, potrebbe avere un nome e un pacchetto completamente diversi (quindi i nomi delle classi ovviamente non corrisponderanno) ma è ancora di tipo C.
  • Per lo stesso motivo ereditario Class.isAssignableFrom()non è simmetrico :
    obj.getClass().isAssignableFrom(C.class)ritornerebbe falsese il tipo di objè una sottoclasse di C.

6
Questo è davvero un ottimo riassunto di molte delle insidie ​​dei diversi metodi. Grazie per un commento così completo!
Kelsin,

32

Puoi usare:

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH. Ma penso che la maggior parte delle volte non sia una buona pratica usarlo per il flusso di controllo o qualcosa di simile ...


L'ho usato per creare un logger generico, quindi ho inviato l'oggetto al logger e registra in base al nome della classe dell'oggetto, piuttosto che fornire tag tag o stringa di log ogni volta. grazie
MBH,

24

Qualsiasi utilizzo di uno qualsiasi dei metodi suggeriti è considerato un odore di codice basato su un cattivo design OO.

Se il tuo design è buono, non dovresti trovarti a dover usare getClass()o instanceof.

Qualunque dei metodi suggeriti farà, ma solo qualcosa da tenere a mente, dal punto di vista del design.


3
Sì, probabilmente il 99% degli usi di getClass e instanceof può essere evitato con chiamate a metodi polimorfici.
Bill the Lizard,

3
sono d'accordo. in questo caso sto lavorando con oggetti generati da XML seguendo uno schema mal progettato di cui non ho la proprietà.
vettore

28
Non necessariamente. A volte la separazione delle interfacce è buona. Ci sono momenti in cui vuoi sapere se A è una B, ma non vuoi rendere obbligatorio che A sia una B, poiché solo A è richiesto per la maggior parte delle funzionalità: B ha funzionalità opzionali.
MetroidFan2002,

8
Inoltre, ci sono momenti in cui è necessario assicurarsi che l'oggetto sia della stessa classe con cui si sta confrontando; ad esempio, mi piace sostituire il metodo uguale a Oggetto quando creo la mia classe. Verifico sempre che l'oggetto che entra sia della stessa classe.
StackOverflow

58
Inoltre, direi che dire alla gente che qualcosa non va senza spiegare esattamente perché o dare un riferimento a un documento, un libro o qualsiasi altra risorsa in cui viene spiegato il problema non è considerato costruttivo. Pertanto e sapendo che sono in StackOverflow, non so perché la gente abbia votato così tanto a questa risposta. Qui sta cambiando qualcosa ...
Adrián Pérez,

15

In questo caso possiamo usare la riflessione

objectName.getClass().getName();

Esempio:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

In questo caso otterrai il nome della classe quale oggetto passa alla HttpServletRequestvariabile di riferimento dell'interfaccia.


questo è corretto. l'utilizzo di solo obj.getClass()restituirà className, prefixex con la parolaclass
x6iae

request.getClass().getName();stampa tutto il pacchetto! insieme al nome della classe
shareef,

13

C'è anche un .isInstancemetodo sulla Classclasse " ". se ottieni la classe di un oggetto tramite myBanana.getClass()puoi vedere se il tuo oggetto myAppleè un'istanza della stessa classe di myBananavia

myBanana.getClass().isInstance(myApple)

1

verificare con isinstance()non sarebbe sufficiente se si desidera sapere in fase di esecuzione. uso:

if(someObject.getClass().equals(C.class){
    // do something
}

0

Uso la funzione di soffiaggio nella mia classe GeneralUtils, controllo che possa essere utile

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}

0

Ho usato i generici Java 8 per ottenere qual è l'istanza dell'oggetto in fase di runtime piuttosto che dover usare switch case

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

passare qualsiasi tipo di dati e il metodo stamperà il tipo di dati passati durante la chiamata. per esempio

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

Di seguito è l'output

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
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.