4.14 | Die Meta-Klasse Class |
Die Objekte der Klasse Class stellen gewissermaßen Meta-Objekte dar, weil sie Informationen über eine Klasse zur Verfügung stellen, die sie repräsentieren. Mit Class-Objekten kann man:Jeder Klasse in der Virtual Machine ist eineindeutig ein Class-Objekt zugeordnet. Es gibt also keine zwei Class-Exemplare, die dieselbe Klasse repräsentieren. Im Abschnitt 11.7.3 wird gezeigt, wie man diese Eigenschaft nutzen kann, um Threads zu synchronisieren.
- Ein neues Exemplar der repräsentierten Klasse erzeugen
- Den vollständigen Klassennamen eines Objekts dynamisch ermitteln (Methode getName()) sowie über verschiedene andere Inspektionsmethoden Informationen über das Objekt erhalten
- Klassen in die Virtual Machine laden (Methode forName())
- Informationen über die Bestandteile der repräsentierten Klasse abrufen. Die Methode getMethods() liefert ein Array von Objekten, die die Methoden der betreffenden Klasse repräsentieren. Entsprechend gibt es auch die Methoden getConstructors() und getFields(). Alle drei Methoden liefern Arrays von Objekten, die im Paket java.lang.reflect definiert sind.
Es gibt drei Möglichkeiten, um an das Class-Objekt einer Klasse zu kommen:Eine Kombination der Methoden forName() und newInstance() kann man dazu verwenden, um Exemplare von Klassen völlig dynamisch zu erzeugen, ohne dass die Klassen beim Kompilieren bekannt sein müssen. Die Methode in diesem Beispiel erzeugt ein Exemplar zum übergebenen Klassennamen:
- Mit der Methode getClass(), die in Object definiert ist. Diese Variante setzt voraus, dass man eine Referenz auf ein Objekt hat, dessen Class-Objekt ermittelt werden soll.
// o: Referenz auf beliebiges Objekt Class c = o.getClass();- Weiterhin definiert Class die Methode forName(), der ein Klassenname als String übergeben wird und die ein Class-Objekt für diese Klasse zurückgibt. Hierzu lädt forName() die Klasse zuvor in die Virtual Machine. In diesem Beispiel wird das Class-Objekt für die Klasse Vector abgerufen:
try { Class c = Class.forName("java.util.Vector"); } catch(ClassNotFoundException e) { }Da es passieren kann, dass der Bytecode der gewünschten Klasse zur Laufzeit nicht verfügbar ist, muss eine Exception abgefangen werden.Das in Version 1.1 eingeführte Konstrukt der Class-Literale gestattet es, Class-Objekte auch deklarativ zu ermitteln:
Class c = java.util.Vector.class;Bei dieser Variante wird bereits beim Kompilieren geprüft, ob der Bytecode der betreffenden Klasse vorhanden ist.public Object createInstance(String name) throws Exception { // Class-Objekt holen Class c = Class.forName(name); // Exemplar erzeugen und zurückliefern return c.newInstance(); }In diesem Beispiel wird der parameterlose Konstruktor der Klasse aufgerufen. Wenn ein Konstruktor mit Parametern aufgerufen werden soll, muss auf das Reflection API zurückgegriffen werden.In Java 1.1 wurden auch Class-Objekte für die einfachen Datentypen eingeführt. Diese können entweder über das statische Datenelement TYPE der jeweiligen Wrapper-Klasse oder mit einem Class-Literal ermittelt werden. Das Class-Objekt für den Typ int kann man also mit einer dieser beiden Zeilen erhalten:
Class c1 = Integer.TYPE; Class c2 = int.class;Auch für den Typ void wurde eine neue Wrapper-Klasse definiert, deren einziger Bestandteil TYPE ist. Ob ein Class-Objekt eine Klasse oder einen einfachen Datentyp repräsentiert, kann mit dessen Methode isPrimitive() ermittelt werden.
Die Class-Objekte für die einfachen Datentypen wurden im Rahmen des in Version 1.1 eingeführten Reflection API erforderlich, um ein einheitliches Konzept zur Meta-Darstellung von Datentypen zu haben. So definiert die Klasse Field, die im Paket java.lang.reflect definiert ist und ein Datenelement einer Klasse repräsentiert, eine Methode getType(), die den Typ des Datenelements in Form eines Class-Objekts liefert. Ohne Class-Objekte für einfache Datentypen wäre dies so nicht möglich.