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.