Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Generics, innere Klassen
10 Die Klassenbibliothek
11 Threads und nebenläufige Programmierung
12 Datenstrukturen und Algorithmen
13 Raum und Zeit
14 Dateien und Datenströme
15 Die eXtensible Markup Language (XML)
16 Grafische Oberflächen mit Swing
17 Grafikprogrammierung
18 Netzwerkprogrammierung
19 Verteilte Programmierung mit RMI und Web–Services
20 JavaServer Pages und Servlets
21 Applets
22 Midlets und die Java ME
23 Datenbankmanagement mit JDBC
24 Reflection und Annotationen
25 Logging und Monitoring
26 Sicherheitskonzepte
27 Java Native Interface (JNI)
28 Dienstprogramme für die Java-Umgebung
Stichwort

Download:
- ZIP, ca. 14,1 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel (8. Auflage) von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel (8. Auflage)

Java ist auch eine Insel (8. Aufl.)
8., aktual. Auflage, geb., mit DVD
1.475 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1371-4
Pfeil 24 Reflection und Annotationen
Pfeil 24.1 Metadaten
Pfeil 24.1.1 Metadaten durch JavaDoc-Tags
Pfeil 24.2 Metadaten der Klassen mit dem Class-Objekt
Pfeil 24.2.1 An ein Class-Objekt kommen
Pfeil 24.2.2 Was das Class-Objekt beschreibt
Pfeil 24.2.3 Der Name der Klasse
Pfeil 24.2.4 instanceof mit Class-Objekten
Pfeil 24.2.5 Oberklassen finden
Pfeil 24.2.6 Implementierte Interfaces einer Klasse oder eines Interfaces
Pfeil 24.2.7 Modifizierer und die Klasse Modifier
Pfeil 24.2.8 Die Arbeit auf dem Feld
Pfeil 24.3 Attribute, Methoden und Konstruktoren
Pfeil 24.3.1 Reflections – Gespür für Attribute einer Klasse
Pfeil 24.3.2 Methoden einer Klasse erfragen
Pfeil 24.3.3 Properties einer Bean erfragen
Pfeil 24.3.4 Konstruktoren einer Klasse
Pfeil 24.3.5 Annotationen
Pfeil 24.4 Objekte erzeugen und manipulieren
Pfeil 24.4.1 Objekte erzeugen
Pfeil 24.4.2 Die Belegung der Variablen erfragen
Pfeil 24.4.3 Eine generische toString()-Funktion
Pfeil 24.4.4 Variablen setzen
Pfeil 24.4.5 Private Attribute ändern
Pfeil 24.5 Methoden aufrufen
Pfeil 24.5.1 Statische Methoden aufrufen
Pfeil 24.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen
Pfeil 24.6 Annotationen
Pfeil 24.6.1 Neue Annotationen definieren
Pfeil 24.6.2 Annotationen mit genau einem Element
Pfeil 24.6.3 Beliebige Schlüssel-Werte-Paare
Pfeil 24.6.4 Vorbelegte Elemente
Pfeil 24.6.5 Annotieren von Annotationstypen
Pfeil 24.6.6 Annotationen zur Laufzeit auslesen
Pfeil 24.6.7 Mögliche Nachteile von Annotationen
Pfeil 24.6.8 XDoclet
Pfeil 24.7 Zum Weiterlesen


Galileo Computing - Zum Seitenanfang

24.4 Objekte erzeugen und manipulieren Zur nächsten ÜberschriftZur vorigen Überschrift

Nachdem wir nun genügend über das Ausfragen von Klassen-, Variablen-, Methoden- und Konstruktor-Objekten wissen, wollen wir aktiv eigene Objekte erzeugen, Werte von Variablen abfragen und verändern sowie Methoden dynamisch per Reflection aufrufen.


Galileo Computing - Zum Seitenanfang

24.4.1 Objekte erzeugen Zur nächsten ÜberschriftZur vorigen Überschrift

Der new-Operator erzeugt in Java zur Laufzeit ein Exemplar einer Klasse. Der Compiler muss dazu den Namen der Klasse kennen, sodass er einen passenden Konstruktor-Aufruf erzeugen kann. Kennen wir aber erst später zur Laufzeit den Namen der gewünschten Klasse für unser Objekt, so fällt die new-Operation flach, weil für diesen Spezialfall der new-Operator nicht gedacht ist.

Um Exemplare bestimmter Klassen dynamisch zu erzeugen, brauchen wir wieder ein passendes Class-Objekt. Nun holen wir uns mit getConstructor() ein Konstruktor-Objekt, das den gewünschten Konstruktor beschreibt. Jedes Konstruktor-Objekt kennt eine newInstance(Object[])-Methode, die ein neues Exemplar erschafft, indem sie den zugrundeliegenden Konstruktor aufruft. Der Parameter von newInstance() ist ein Feld von Werten, die an den echten Konstruktor gehen. Glücklicherweise kennt Java anonyme Arrays, sodass wenig zu schreiben bleibt. Bei einem parameterlosen Konstruktor können wir einfach newInstance(null) aufrufen.


Beispiel Ein Reflection-Konstruktor erzeugt ein Point-Objekt mit den Koordinaten 10, 20.

Listing 24.11 com/tutego/insel/meta/CreateObject.java, main()

Class<Point> pointClass = Point.class; 
Constructor<Point> constructor = 
  pointClass.getConstructor( int.class, int.class ); 
Point p = constructor.newInstance( 10, 20 ); 
System.out.println( p );


final class java.lang.Class<T> 
implements Serializable, GenericDeclaration, Type, AnnotatedElement

  • Constructor<T> getConstructor( Class... parameterTypes ) throws NoSuchMethodException Liefert den sichtbaren Konstruktor mit dem gewünschten Typ.

final class java.lang.reflect.Constructor<T> 
extends AccessibleObject 
implements GenericDeclaration, Member

  • T newInstance( Object... initargs ) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException Erzeugt ein neues Exemplar, indem es den durch das Constructor-Objekt repräsentierten Konstruktor mit den im Array angegebenen Parametern aufruft. Auf einige Exceptions ist zu achten. IllegalAccessException: Auf den Konstruktor kann nicht zugegriffen werden (zum Beispiel, weil er privat ist). IllegalArgumentException: Die Anzahl der Parameter ist falsch beziehungsweise eine Konvertierung der Parameterwerte in die benötigten Typen nicht möglich. InstantiationException: Das Constructor-Objekt bezieht sich auf einen Konstruktor einer abstrakten Klasse.

InvocationTargetException

Die Ausnahme InvocationTargetException ist keine RuntimeException und kommt bei zwei Methoden aus der Reflection-API vor:

  • newInstance() zum Erzeugen von Objekten bei Constructor
  • invoke() zum Aufruf von Methoden bei Method.

Die InvocationTargetException ist Mantel um genau die Ausnahme, die der aufgerufene Konstruktor beziehungsweise die Methode ausgelöst hat. Löst der Konstruktor oder die Methode eine Ausnahme aus, so generiert die JVM eine InvocationTargetException und lässt uns mit getCause() beziehungsweise mit getTargetException() den Grund als Throw-able erfragen.


Galileo Computing - Zum Seitenanfang

24.4.2 Die Belegung der Variablen erfragen Zur nächsten ÜberschriftZur vorigen Überschrift

Schreiben wir einen GUI-Builder oder einen Debugger, so reicht es nicht aus, nur die Namen und Datentypen der Variablen zu kennen. Wir wollen auch auf ihre Inhalte lesend und schreibend zugreifen. Das ist mit Hilfe der verschiedenen getXXX()-Methoden für ein Field-Objekt leicht machbar. Der erste Schritt besteht also wieder darin, ein Class-Objekt zu erfragen. Dann besorgen wir uns mittels getFields() ein Array von Attributbeschreibungen – oder mit getFields(String) ein spezielles Attribut – und nehmen das Field-Objekt für unsere gewünschte Variable. Den Wert, den das Field dann speichert, erfragt die Methode get(). Sie ist auf allen Variablentypen möglich und konvertiert automatisch in Wrapper-Objekte, wenn der Typ primitiv war. Die Field-Klasse bietet einige spezielle getXXX()-Methoden, um besonders einfach an die Werte von Variablen primitiven Typs zu gelangen. So liefert getDouble() einen double-Wert und getInt() ein int. Wir müssen daran denken, dass Illegal-ArgumentException und IllegalAccessException bei falschem Zugriff auftreten können.

Alle getXXX()-Methoden zum Erfragen – und auch setXXX()-Methoden zum Setzen – erwarten ein Argument mit dem Verweis auf das Objekt, welches die Variable besitzt. Das Argument wird ignoriert (und sollte null sein), wenn es sich um eine statische Variable handelt.

Rechtecke erzeugen und erfragen

Ein Programm soll ein Rectangle-Objekt mit einer Belegung für x, y, Höhe und Breite erzeugen. Anschließend erfragt getField(String) das Field-Objekt für eine Beschreibung der Variablen mit dem gegebenen Namen. Das Field-Objekt gibt mit getXXX() den Inhalt der Variablen preis. Um das Prinzip zu demonstrieren, erfragt die get()-Methode die Höhe height, die ein Integer-Objekt zurückgibt. Alle anderen Ganzzahlwerte liefert die spezialisierte Helfermethode getInt().

Listing 24.12 com/tutego/insel/meta/GetFieldElements.java

package com.tutego.insel.meta; 
 
import java.lang.reflect.*; 
 
class GetFieldElements 
{ 
  public static void main( String[] args ) 
  { 
    Object   o = new java.awt.Rectangle( 11, 22, 33, 44 ); 
    Class<?> c = o.getClass(); 
 
    try 
    { 
      Field heightField = c.getField( "height" ), 
            widthField  = c.getField( "width" ), 
            xField      = c.getField( "x" ), 
            yField      = c.getField( "y" ); 
 
      Integer height = (Integer) heightField.get( o ); 
 
      int width = widthField.getInt( o ), 
              x = xField.getInt( o ), 
              y = yField.getInt( o ); 
 
      String s = c.getName() + "[x=" + x + ",y=" + y + 
                 ",width=" + width + ",height=" + height + "]"; 
 
      System.out.println( s ); // java.awt.Rectangle[x=11,y=22,width=33,height=44] 
      System.out.println( o ); // java.awt.Rectangle[x=11,y=22,width=33,height=44] 
    } 
    catch ( NoSuchFieldException e ) { 
      e.printStackTrace(); 
    } 
    catch ( SecurityException e ) { 
      e.printStackTrace(); 
    } 
    catch ( IllegalAccessException e ) { 
      e.printStackTrace(); 
    } 
  } 
}

Es erzeugt nun nach dem Aufruf die Ausgabe:

java.awt.Rectangle[x=11,y=22,width=33,height=44] 
java.awt.Rectangle[x=11,y=22,width=33,height=44]

final class java.lang.reflect.Field 
extends AccessibleObject 
implements Member

  • String getName()
    Liefert den Namen der Variablen. Diese Methode ist Teil der Schnittstelle Member.
  • int getModifiers()
    Liefert die Modifizierer. Diese Methode ist Teil der Schnittstelle Member.
  • Object get( Object obj ), boolean getBoolean( Object obj ), byte getByte( Object
    obj )
    , char getChar( Object obj ), double getDouble( Object obj ), float getFloat( Object obj ), int getInt( Object obj ), long getLong( Object obj ), short getShort( Object obj ) Erfragt den Wert eines Attributs. Die Referenz von obj zeigt auf das Objekt, welches das Attribut enthält. Es sollte null übergeben werden, wenn es sich um eine statische Variable handelt.

Galileo Computing - Zum Seitenanfang

24.4.3 Eine generische toString()-Funktion Zur nächsten ÜberschriftZur vorigen Überschrift

Die toString()-Methode ist für viele Klassen nicht überlebenswichtig, aber außerordentlich praktisch. Viel zu schade, hier Zeit für die Entwicklung zu investieren. Toll wäre es, wenn toString() ganz automatisch die Attribute und Belegungen analysiert und ausgibt. Aber wer Allgemeines sucht, findet die Antwort in Reflection. Wir schreiben einfach eine statische Methode toString(Object) in eine Hilfsklasse und erfragen dann alle Attribute und die Werte des zu untersuchenden Objekts. Etwas Programmieraufwand müssen wir noch in die Behandlung der Oberklasse investieren, denn Reflection auf einem Objekt zeigt nur die in der Klasse definierten Attribute, nicht aber die geerbten Attribute an. Die Lösung ergibt sich fast von selbst:

Listing 24.13 com/tutego/insel/meta/ToStringHelper.java

package com.tutego.insel.meta; 
 
import java.lang.reflect.AccessibleObject; 
import java.lang.reflect.Field; 
import java.util.ArrayList; 
 
public class ToStringHelper 
{ 
  public static String toString( Object o ) 
  { 
    ArrayList<String> list = new ArrayList<String>(); 
 
    toString( o, o.getClass(), list ); 
 
    return o.getClass().getName().concat( list.toString() ); 
 } 
 
 private static void toString( Object o, Class<?> clazz, ArrayList<String> list ) 
 { 
  Field[] fields = clazz.getDeclaredFields(); 
  AccessibleObject.setAccessible( fields, true ); 
 
  for ( Field f : fields ) { 
   try { 
    list.add( f.getName() + "=" + f.get(o) ); 
   } 
   catch ( IllegalAccessException e ) { e.printStackTrace(); } 
  } 
 
  if ( clazz.getSuperclass().getSuperclass() != null ) 
    toString( o, clazz.getSuperclass(), list ); 
 } 
}

Die private Funktion toString(Object, Class, ArrayList) dient eigentlich nur dem rekursiven Aufruf durch die Oberklassen. Falls es eine Oberklasse gibt, also clazz.getSuperclass().getSuperclass() ein Objekt liefert, müssen wir für die Oberklasse ebenfalls die Attribute ablaufen. Das machen wir rekursiv.

Testen wir anschließend ToStringHelper in einer Klasse ToStringHelperDemo, die von Ober abgeleitet ist. Damit bekommen wir zwei Attribute in der Oberklasse. Eines davon ist interessant (die Variable i), denn die Unterklasse überdeckt sie. Dennoch findet toString() beide Belegungen. Wäre das nicht erwünscht, müssten wir einfach die Liste durchschauen und suchen, ob schon ein Attribut mit dem gleichen Namen vorhanden ist. Da der Algorithmus rekursiv erst die Unterklasse und dann die Oberklasse(n) durchsucht, bekommen wir auch die Attribute in dem sichtbaren Bereich, wie sie auch der Benutzer sieht.

Listing 24.14 com/tutego/insel/meta/ToStringHelperDemo.java

package com.tutego.insel.meta; 
 
class Ober 
{ 
  int i = 123; 
  /* private */double d = 3.1415; 
} 
 
public class ToStringHelperDemo extends Ober 
{ 
  String hello = "world"; 
  int    i     = 42; 
 
  public static void main( String[] args ) 
  { 
    ToStringHelperDemo t = new ToStringHelperDemo(); 
 
    System.out.println( ToStringHelper.toString( t ) ); 
    // ToStringHelperTest[hello=world, i=42, i=123, d=3.1415] 
  } 
}

Galileo Computing - Zum Seitenanfang

24.4.4 Variablen setzen Zur nächsten ÜberschriftZur vorigen Überschrift

Bei Debuggern oder grafischen Editoren ist es nur eine Seite der Medaille, die Werte von Variablen anzuzeigen. Hinzu kommt noch das Setzen der Werte von Variablen. Dies ist aber genauso einfach wie das Abfragen. An Stelle der getXXX()-Methoden kommen nun verschiedene setXXX()-Methoden zum Einsatz. So trägt setBoolean() einen Wahrheitswert oder setDouble() eine Fließkommazahl in eine Variable ein. Eine allgemeine set()-Methode dient Objektreferenzen wie im Fall von get(). Die Methode set() nimmt ebenso Wrapper-Objekte für Variablen von primitiven Datentypen. Die folgenden set<Typ>()-Methoden setzen daher alle »ihren« Datentyp. Wir müssen aber dafür sorgen, dass die Variable existiert und wir Zugriff darauf haben. In allen Fällen muss auf IllegalArgumentException und Illegal-AccessException geachtet werden.

Das folgende Programm erzeugt klassisch ein Point-Objekt mit dem Konstruktor, der x und y setzt. Anschließend verändert die eigene Methode modify() ein gewünschtes Attribut.

Listing 24.15 com/tutego/insel/meta/SetFieldElements.java

package com.tutego.insel.meta; 
 
import java.lang.reflect.*; 
import java.awt.*; 
 
class SetFieldElements 
{ 
  public static void main( String[] args ) 
  { 
    Point p = new Point( 11, 22 ); 
    System.out.println( p ); 
 
    modify( p, "x", 1111 );   // java.awt.Point[x=11,y=22] 
    modify( p, "y", 2222 );   // java.awt.Point[x=1111,y=2222] 
    System.out.println( p ); 
 
    modify( p, "z", 0 );      // java.lang.NoSuchFieldException: z 
  } 
 
  static void modify( Object o, String name, Integer param ) 
  { 
    try 
    { 
      Field field = o.getClass().getField( name ); 
      field.set( o, param ); 
    } 
    catch ( NoSuchFieldException e ) { 
      e.printStackTrace(); 
    } 
    catch ( IllegalAccessException e ) { 
      e.printStackTrace(); 
    } 
  } 
}

Die Veränderung der Variablen erfolgt mit der set()-Methode. Da wir primitive Datentypen übergeben, wickeln wir sie für die modify()-Methode in ein Integer-Objekt ein, das im Quellcode durch das Boxing nicht explizit programmiert ist, aber der Compiler vornimmt. Für bekannte Typen könnten wir neben der allgemeinen Methode set() auch etwa setInt() verwenden.


final class java.lang.reflect.Field 
extends AccessibleObject 
implements Member

  • void set( Object obj, Object value )
    Setzt das Attribut des Objekts obj, das dieses Field-Objekt repräsentiert, auf den neuen Wert value.
  • void setBoolean( Object obj, boolean z )
  • void setByte( Object obj, byte b )
  • void setChar( Object obj, char c )
  • void setDouble( Object obj, double d )
  • void setFloat( Object obj, float f )
  • void setInt( Object obj, int i )
  • void setLong( Object obj, long l )
  • void setShort( Object obj, short s )
    Belegt das Feld eines Objekts obj mit einem primitiven Element.

Galileo Computing - Zum Seitenanfang

24.4.5 Private Attribute ändern topZur vorigen Überschrift

Wenn es der Sicherheitsmanager zulässt, kann ein Programm auch private- oder protected-Attribute ändern und Methoden/Konstruktoren eingeschränkter Sichtbarkeit aufrufen. Schlüsselfigur in diesem Spiel ist die Oberklasse java.lang.reflect.AccessibleObject, die den Klassen Constructor, Field und Method die Methode setAccessible(boolean) vererbt. Ist das Argument true, und der Sicherheitsmanager lässt die Operation zu, lässt sich auf jedes Element, also Konstruktor, Attribut oder Methode, zugreifen.

Listing 24.16 com/tutego/insel/meta/ReadPrivate.java

package com.tutego.insel.meta; 
 
public class ReadPrivate 
{ 
  @SuppressWarnings( "all" ) 
  private String privateKey = "Schnuppelhase"; 
 
  public static void main( String[] args ) throws Exception 
  { 
    ReadPrivate key = new ReadPrivate(); 
    Class<?> c = key.getClass(); 
    java.lang.reflect.Field field = c.getDeclaredField( "privateKey" ); 
    field.setAccessible( true ); 
    System.out.println( field.get(key) ); // Schnuppelhase 
    field.set( key, "Schnuckibutzihasidrachelchen"); 
    System.out.println( field.get(key) ); // Schnuckibutzihasidrachelchen 
  } 
}


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< zurück
  Zum Katalog
Zum Katalog: Java ist auch eine Insel





Java ist auch eine Insel
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Tipp
Zum Katalog: Coding for Fun





 Coding for Fun


 Buchempfehlungen
Zum Katalog: Objektorientierte Programmierung





 Objektorientierte
 Programmierung


Zum Katalog: Einstieg in Eclipse 3.4






 Einstieg in
 Eclipse 3.4


Zum Katalog: Java 6 lernen mit Eclipse






 Java 6 lernen
 mit Eclipse


Zum Katalog: NetBeans Platform 6






 NetBeans
 Platform 6


Zum Katalog: Java und XML






 Java und XML


Zum Katalog: Visual C# 2008






 Visual C# 2008


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: C++ von A bis Z






 C++ von A bis Z


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de