2011-01-03 28 views
132

Estoy jugando con la API de reflexión de Java y tratando de manejar algunos campos. Ahora estoy atascado con la identificación del tipo de mis campos. Las cadenas son fáciles, solo haz myField.getType().equals(String.class). Lo mismo aplica para otras clases no derivadas. ¿Pero cómo verifico las clases derivadas? P.ej. LinkedList como subclase de List. No puedo encontrar ningún método isSubclassOf(...) o extends(...). ¿Tengo que recorrer todos los getSuperClass() y encontrar mi supeclass por mi cuenta?Comprueba si una clase es una subclase de otra clase en Java

+9

'LinkedList' no es una subclase de' List'. Es una * implementación * de 'List'. –

+1

* Subtipo * podría ser un término mejor – jpaugh

Respuesta

292

desea que este método:

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

donde, en general, List (arriba) debe sustituirse por superclass y myClass debe sustituirse por subclass

Desde el JavaDoc:

Determina si la clase o interfaz representada por este objeto Class es th th El mismo que, o es una superclase o superinterfaz de, la clase o interfaz representada por el parámetro Class especificado. Devuelve true si es así; de lo contrario, devuelve false. Si este objeto Class representa un tipo primitivo, este método devuelve true si el parámetro Class especificado es exactamente este objeto Class; de lo contrario, devuelve false.

Referencia:


relacionadas:

a) Comprobar si un objeto es una instancia de una clase o interfaz (incluyendo subclases) se conocen en tiempo de compilación:

boolean isInstance = someObject instanceof SomeTypeOrInterface; 

Ejemplo:

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

b) comprobar si un objeto es una instancia de una clase o interfaz (incluyendo las subclases) sólo se conoce en tiempo de ejecución:

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

Ejemplo:

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

Tenga en cuenta el esquema: 'SUPERCLASS.isAssignableFrom (SUBCLASS)' Esto me confundió primero, aunque en realidad es obvio teniendo en cuenta la nomenclatura. – codepleb

+5

@TrudleR Estoy de acuerdo. Algo como 'SUPERCLASS.isExtendedBy (SUBCLASS)' sería mucho más fácil de entender –

+0

@SeanPatrickFloyd en realidad 'isExtendedBy' es un nombre incorrecto ya que' CLASS.isAssignableFrom (CLASS) 'sería verdadero (y por lo tanto' CLASS.isExtendedBy (CLASS) ' también). Esto no sería lo que esperaba. – Qw3ry

22

Otra opción es instanceof:

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

Buena llamada (+1). Y luego está la combinación de los dos mecanismos: 'Class.isInstance (object)' http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#isInstance%28java. lang.Object% 29 –

+3

Esto implicaría que usted instancia ese 'Campo'. Pero solo quiero "mirar" mi clase y sus campos, no quiero "probarlos". – craesh

+0

Veo este método mucho más limpio y claro que el modo "isAssignableFrom", en el caso de que necesite verificar el árbol de herencia de un objeto. – cbuchart

8

instanceof trabajos sobre los casos, es decir, en los objetos. A veces quieres trabajar directamente con las clases. En este caso, puede utilizar el método asSubClass de la clase Class. Algunos ejemplos:

1)

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

este pasará a través sin problemas porque JFrame es subclase de Object. c contendrá un objeto Class que representa la clase JFrame.

2)

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

Se iniciará un java.lang.ClassCastException porque JFrame no es subclase de JButton. c no se inicializará.

3)

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

este pasará a través sin problemas porque JFrame implementa la interfaz java.io.Serializable. c contendrá un objeto Class que representa la clase JFrame.

Por supuesto, se deben incluir las importaciones necesarias.

4

Esto funciona para mí:

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

Funciona bien, pero es posible que deba agregar una comprobación nula después de clazz = clazz.getSuperclass() en caso de que golpee java.lang.Object que no tenga una superclase. –

1

Un método recrursive para comprobar si un clazz es un "niño" de una superclase ...

Versión mejorada de la respuesta de @ To_Kra:

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

Esta es una versión mejorada de la respuesta de @ schuttek. Se ha mejorado porque devuelve correctamente false para las primitivas (por ejemplo, isSubclassOf (int.class, Object.class) => false) y también maneja correctamente las interfaces (por ejemplo, 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; 
    } 
} 
Cuestiones relacionadas