Controllare se un oggetto classe è una sottoclasse di un altro oggetto classe in Java


197

Sto giocando con l'API di riflessione di Java e sto cercando di gestire alcuni campi. Ora sono bloccato con l'identificazione del tipo dei miei campi. Le stringhe sono facili, basta myField.getType().equals(String.class). Lo stesso vale per altre classi non derivate. Ma come posso controllare le classi derivate? Ad esempio LinkedListcome sottoclasse di List. Non riesco a trovare alcuna isSubclassOf(...)o di extends(...)metodo. Devo percorrere tutto getSuperClass()e trovare la mia supeclass per conto mio?


11
LinkedListnon è una sottoclasse di List. È un'implementazione di List.
TJ Crowder,

2
Sottotipo potrebbe essere un termine migliore
jpaugh

Risposte:


403

Vuoi questo metodo:

boolean isList = List.class.isAssignableFrom(myClass);

dove in generale, List(sopra) dovrebbe essere sostituito con superclasse myClassdovrebbe essere sostituito consubclass

Da JavaDoc :

Determina se la classe o l'interfaccia rappresentata da questo Classoggetto è uguale o è una superclasse o superinterfaccia della classe o dell'interfaccia rappresentata dal Classparametro specificato . Ritorna in truetal caso; altrimenti ritorna false. Se questo Classoggetto rappresenta un tipo primitivo, questo metodo restituisce truese il Classparametro specificato è esattamente questo Classoggetto; altrimenti ritorna false.

Riferimento:


Relazionato:

a) Verifica se un oggetto è un'istanza di una classe o interfaccia (comprese le sottoclassi) che conosci al momento della compilazione:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Esempio:

assertTrue(Arrays.asList("a", "b", "c") instanceof List<?>);

b) Verifica se un oggetto è un'istanza di una classe o interfaccia (comprese le sottoclassi) che conosci solo in fase di esecuzione:

Class<?> typeOrInterface = // acquire class somehow
boolean isInstance = typeOrInterface.isInstance(someObject);

Esempio:

public boolean checkForType(Object candidate, Class<?> type){
    return type.isInstance(candidate);
}

21
Nota lo schema: SUPERCLASS.isAssignableFrom(SUBCLASS)questo mi ha prima confuso, anche se in realtà è ovvio considerando la denominazione.
codepleb,

7
@TrudleR Sono d'accordo. Qualcosa del genere SUPERCLASS.isExtendedBy(SUBCLASS)sarebbe molto più facile da capire
Sean Patrick Floyd,

@SeanPatrickFloyd in realtà isExtendedByè un brutto nome come CLASS.isAssignableFrom(CLASS)sarebbe vero (e quindi CLASS.isExtendedBy(CLASS)anche). Questo non sarebbe quello che mi aspettavo.
Qw3ry,

@ Qw3ry sì, suppongo che sia anche quello che gli autori di Api hanno pensato :-)
Sean Patrick Floyd,

25

Un'altra opzione è instanceof:

Object o =...
if (o instanceof Number) {
  double d = ((Number)o).doubleValue(); //this cast is safe
}

Buona chiamata (+1). E poi c'è anche la combinazione dei due meccanismi: Class.isInstance(object) download.oracle.com/javase/6/docs/api/java/lang/…
Sean Patrick Floyd,

5
Ciò implicherebbe che tu lo installi Field. Ma voglio solo "guardare" la mia classe e i suoi campi, non voglio "provarli".
Craesh,

Vedo questo metodo molto più pulito e chiaro del modo "isAssignableFrom", nel caso in cui sia necessario controllare l'albero di eredità di un oggetto.
cbuchart,

Ricorda che instanceoffunziona anche per i genitori (in questo caso Number) non solo per i bambini
lukaszrys,

9

instanceof funziona su istanze, cioè su Oggetti. A volte vuoi lavorare direttamente con le lezioni. In questo caso è possibile utilizzare il metodo asSubClass della classe Class. Qualche esempio:

1)

    Class o=Object.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

questo andrà a buon fine perché JFrame è una sottoclasse di Object. c conterrà un oggetto Class che rappresenta la classe JFrame.

2)

    Class o=JButton.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

questo avvierà un java.lang.ClassCastException perché JFrame NON è una sottoclasse di JButton. c non verrà inizializzato.

3)

    Class o=Serializable.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

questo andrà a buon fine perché JFrame implementa l'interfaccia java.io.Serializable. c conterrà un oggetto Class che rappresenta la classe JFrame.

Naturalmente le importazioni necessarie devono essere incluse.


5

Questo funziona per me:

protected boolean isTypeOf(String myClass, Class<?> superClass) {
    boolean isSubclassOf = false;
    try {
        Class<?> clazz = Class.forName(myClass);
        if (!clazz.equals(superClass)) {
            clazz = clazz.getSuperclass();
            isSubclassOf = isTypeOf(clazz.getName(), superClass);
        } else {
            isSubclassOf = true;
        }

    } catch(ClassNotFoundException e) {
        /* Ignore */
    }
    return isSubclassOf;
}

1
Funziona bene, ma potresti dover aggiungere un controllo nullo dopo clazz = clazz.getSuperclass () nel caso in cui colpisci java.lang.Object che non ha una super classe.
Jonas Pedersen,

4

Questa è una versione migliorata della risposta di @ schuttek. È stato migliorato perché restituisce correttamente false per primitive (ad es. IsSubclassOf (int.class, Object.class) => false) e gestisce correttamente anche le interfacce (ad es. IsSubclassOf (HashMap.class, Map.class) => true).

static public boolean isSubclassOf(final Class<?> clazz, final Class<?> possibleSuperClass)
{
    if (clazz == null || possibleSuperClass == null)
    {
        return false;
    }
    else if (clazz.equals(possibleSuperClass))
    {
        return true;
    }
    else
    {
        final boolean isSubclass = isSubclassOf(clazz.getSuperclass(), possibleSuperClass);

        if (!isSubclass && clazz.getInterfaces() != null)
        {
            for (final Class<?> inter : clazz.getInterfaces())
            {
                if (isSubclassOf(inter, possibleSuperClass))
                {
                    return true;
                }
            }
        }

        return isSubclass;
    }
}

3

Un metodo ricorsivo per verificare se a Class<?>è una sottoclasse di un'altra Class<?>...

Versione migliorata di @ su Kra 's risposta :

protected boolean isSubclassOf(Class<?> clazz, Class<?> superClass) {
    if (superClass.equals(Object.class)) {
        // Every class is an Object.
        return true;
    }
    if (clazz.equals(superClass)) {
        return true;
    } else {
        clazz = clazz.getSuperclass();
        // every class is Object, but superClass is below Object
        if (clazz.equals(Object.class)) {
            // we've reached the top of the hierarchy, but superClass couldn't be found.
            return false;
        }
        // try the next level up the hierarchy.
        return isSubclassOf(clazz, superClass);
    }
}

3

//Eredità

    class A {
      int i = 10;
      public String getVal() {
        return "I'm 'A'";
      }
    }

    class B extends A {
      int j = 20;
      public String getVal() {
        return "I'm 'B'";
      }
    }

    class C extends B {
        int k = 30;
        public String getVal() {
          return "I'm 'C'";
        }
    }

// Metodi

    public static boolean isInheritedClass(Object parent, Object child) {
      if (parent == null || child == null) {
        return false;
      } else {
        return isInheritedClass(parent.getClass(), child.getClass());
      }
    }

    public static boolean isInheritedClass(Class<?> parent, Class<?> child) {
      if (parent == null || child == null) {
        return false;
      } else {
        if (parent.isAssignableFrom(child)) {
          // is child or same class
          return parent.isAssignableFrom(child.getSuperclass());
        } else {
          return false;
        }
      }
    }

// Prova il codice

    System.out.println("isInheritedClass(new A(), new B()):" + isInheritedClass(new A(), new B()));
    System.out.println("isInheritedClass(new A(), new C()):" + isInheritedClass(new A(), new C()));
    System.out.println("isInheritedClass(new A(), new A()):" + isInheritedClass(new A(), new A()));
    System.out.println("isInheritedClass(new B(), new A()):" + isInheritedClass(new B(), new A()));


    System.out.println("isInheritedClass(A.class, B.class):" + isInheritedClass(A.class, B.class));
    System.out.println("isInheritedClass(A.class, C.class):" + isInheritedClass(A.class, C.class));
    System.out.println("isInheritedClass(A.class, A.class):" + isInheritedClass(A.class, A.class));
    System.out.println("isInheritedClass(B.class, A.class):" + isInheritedClass(B.class, A.class));

//Risultato

    isInheritedClass(new A(), new B()):true
    isInheritedClass(new A(), new C()):true
    isInheritedClass(new A(), new A()):false
    isInheritedClass(new B(), new A()):false
    isInheritedClass(A.class, B.class):true
    isInheritedClass(A.class, C.class):true
    isInheritedClass(A.class, A.class):false
    isInheritedClass(B.class, A.class):false
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.