2011-01-03 14 views
132

Ich spiele mit der Java-Reflektions-API herum und versuche, einige Felder zu behandeln. Jetzt bin ich dabei, den Typ meiner Felder zu identifizieren. Strings sind einfach, tun Sie einfach myField.getType().equals(String.class). Gleiches gilt für andere nicht abgeleitete Klassen. Aber wie überprüfe ich abgeleitete Klassen? Z.B. LinkedList als Unterklasse von List. Ich kann keine isSubclassOf(...) oder extends(...) Methode finden. Muss ich alle getSuperClass() durchgehen und meine eigene Klasse selbst finden?Überprüfen Sie, ob eine Klasse eine Unterklasse einer anderen Klasse in Java ist

+9

'LinkedList' ist keine Unterklasse von' List'. Es ist eine * Implementierung * von 'List'. –

+1

* Untertyp * könnte ein besserer Begriff sein – jpaugh

Antwort

292

Sie wollen diese Methode:

:

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

im Allgemeinen, wo List (oben) sollte sollte mit subclass

Vom JavaDoc ersetzt werden mit superclass und myClass ersetzt werden Bestimmt, ob die durch dieses Class Objekt repräsentierte Klasse oder Schnittstelle entweder th ist Dieselbe oder eine Superklasse oder Superschnittstelle der Klasse oder Schnittstelle, die durch den spezifizierten Parameter Class repräsentiert wird. Es gibt true wenn ja; Andernfalls gibt es false zurück. Wenn dieses Class Objekt einen primitiven Typ darstellt, gibt diese Methode true zurück, wenn der angegebene Class Parameter genau dieses Class Objekt ist; Andernfalls gibt es false zurück.

Referenz:


Verwandte:

a) Überprüfen Sie, ob ein Objekt eine Instanz einer Klasse oder Schnittstelle (einschließlich Subklassen) wissen Sie bei der Kompilierung:

boolean isInstance = someObject instanceof SomeTypeOrInterface; 

Beispiel:

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

b) Überprüfen Sie, ob ein Objekt eine Instanz einer Klasse oder Schnittstelle (einschließlich Unterklassen) ist nur Sie zur Laufzeit kennen:

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

Beispiel:

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

Beachte das Schema: 'SUPERCLASS.isAssignableFrom (SUBCLASS)' Das hat mich zuerst verwirrt, obwohl es in Anbetracht der Namensgebung offensichtlich ist. – codepleb

+5

@TrudleR Ich stimme zu. Etwas wie 'SUPERCLASS.isExtendedBy (SUBCLASS)' wäre viel einfacher zu verstehen –

+0

@SeanPatrickFloyd tatsächlich 'isExtendedBy' ist ein schlechter Name als' CLASS.isAssignableFrom (CLASS) 'wäre wahr (und daher' CLASS.isExtendedBy (CLASS) ') auch). Das wäre nicht das, was ich erwartet hatte. – Qw3ry

22

Eine weitere Option ist instanceof:

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

Guter Anruf (+1). Und dann gibt es noch die Kombination der beiden Mechanismen: 'Class.isInstance (Objekt)' http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#isInstance%28java. lang.Object% 29 –

+3

Dies würde bedeuten, dass Sie das "Feld" instanziieren. Aber ich will nur meine Klasse und ihre Felder "sehen", will sie nicht "ausprobieren". – craesh

+0

Ich sehe diese Methode viel sauberer und klarer als die Methode "isAssignableFrom", falls Sie den Vererbungsbaum eines Objekts überprüfen müssen. – cbuchart

8

Instanceof Arbeiten auf Instanzen, das heißt auf Objekte. Manchmal möchten Sie direkt mit Klassen arbeiten. In diesem Fall können Sie die Methode asSubClass der Klasse Class verwenden. Einige Beispiele:

1)

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

dies durch reibungslos, weil JFrame Unterklasse von Object ist. c enthält ein Klassenobjekt, das die JFrame-Klasse darstellt.

2)

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

dies startet ein java.lang.ClassCastException weil JFrame NICHT Unterklasse von JButton ist. c wird nicht initialisiert.

3)

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

dies durch reibungslos, weil JFrame den java.io.Serializable-Schnittstelle implementiert. c enthält ein Klassenobjekt, das die JFrame-Klasse darstellt.

Natürlich müssen die benötigten Importe enthalten sein.

4

Dies funktioniert für mich:

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

Funktioniert gut, aber Sie müssen möglicherweise einen Null-Test nach clazz = clazz.getSuperclass() hinzufügen, falls Sie java.lang.Object treffen, das keine Super-Klasse hat. –

1

A recrursive Methode zu überprüfen, ob ein clazz ein "Kind" eines übergeordneten Klasse ist ...

Verbesserte Version von @ To_Kra Antwort:

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

Dies ist eine verbesserte Version von @ schutteks Antwort. Es wird verbessert, da es für Primitive korrekt false zurückgibt (z. B. isSubclassOf (int.class, Object.class) => false) und Schnittstellen auch korrekt verarbeitet (z. B. 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; 
    } 
} 
Verwandte Themen