web-dev-qa-db-fra.com

Vérifier si un objet de classe est une sous-classe d'un autre objet de classe dans Java

Je m'amuse avec l'API de réflexion de Java et essaie de gérer certains champs. Maintenant, je suis coincé avec l'identification du type de mes champs. Les chaînes sont faciles, il suffit de faire myField.getType().equals(String.class). Il en va de même pour les autres classes non dérivées. Mais comment vérifier les classes dérivées? Par exemple. LinkedList en tant que sous-classe de List. Je ne trouve aucune méthode isSubclassOf(...) ni extends(...). Dois-je parcourir toutes les getSuperClass() et trouver ma classe par moi-même?

166
craesh

Vous voulez cette méthode:

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

où en général, List (ci-dessus) doit être remplacé par superclass et myClass par subclass

De la JavaDoc :

Détermine si la classe ou l'interface représentée par cet objet Class est identique à ou est une superclasse ou une superinterface de la classe ou de l'interface représentée par le paramètre Class spécifié. Il retourne true si c'est le cas; sinon, il retourne false. Si cet objet Class représente un type primitif, cette méthode retourne true si le paramètre Class spécifié est exactement cet objet Class; sinon, il retourne false.

Référence:


Connexes:

a) Vérifiez si un objet est une instance d'une classe ou d'une interface (y compris des sous-classes) que vous connaissez au moment de la compilation:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Exemple:

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

b) Vérifiez si un objet est une instance d'une classe ou d'une interface (y compris des sous-classes) que vous ne connaissez qu'au moment de l'exécution:

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

Exemple:

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

Une autre option est instanceof:

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

instanceof fonctionne sur des instances, c'est-à-dire sur des objets. Parfois, vous voulez travailler directement avec les classes. Dans ce cas, vous pouvez utiliser la méthode asSubClass de la classe Class. Quelques exemples:

1)

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

cela se passera sans problème car JFrame est une sous-classe de Object. c contiendra un objet Class représentant la classe JFrame.

2)

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

cela lancera un Java.lang.ClassCastException car JFrame n'est PAS une sous-classe de JButton. c ne sera pas initialisé.

3)

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

cela se fera en douceur car JFrame implémente l'interface Java.io.Serializable. c contiendra un objet Class représentant la classe JFrame.

Bien entendu, les importations nécessaires doivent être incluses.

9
Marco

Cela fonctionne pour moi:

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;
}
5
To Kra

Ceci est une version améliorée de la réponse de @ schuttek. Il est amélioré car il renvoie correctement false pour les primitives (par exemple, isSubclassOf (int.class, Object.class) => false) et gère correctement les interfaces (par exemple, 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;
    }
}
4
user2415587

Une méthode récursive pour vérifier si un Class<?> est une sous-classe d'un autre Class<?>...

Version améliorée de @ To Kra 's answer :

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
schuttek

//Héritage

    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'";
        }
    }

// Méthodes

    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;
        }
      }
    }

// Teste le code

    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));

//Résultat

    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
1
chepe lucho