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 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort
Download: - ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /Java-Insel | vor >>
Java ist auch eine Insel von Christian Ullenboom Programmieren mit der Java Standard Edition Version 6
Java ist auch eine Insel 7., aktualisierte Auflage geb., mit DVD (November 2007) 1.492 S., 49,90 Euro Galileo Computing ISBN 978-3-8362-1146-8 |
| 23 Reflection und Annotationen
|  | 23.1 Metadaten
|  |  | 23.1.1 Metadaten durch Java-Doc Tags
|  |  | 23.1.2 XDoclet
|  | 23.2 Metadaten der Klassen mit dem Class-Objekt
|  |  | 23.2.1 An ein Class-Objekt kommen
|  |  | 23.2.2 Was das Class-Objekt beschreibt
|  |  | 23.2.3 Der Name der Klasse
|  |  | 23.2.4 instanceof mit Class-Objekten
|  |  | 23.2.5 Oberklassen finden
|  |  | 23.2.6 Implementierte Interfaces einer Klasse oder eines Interfaces
|  |  | 23.2.7 Modifizierer und die Klasse Modifier
|  |  | 23.2.8 Die Arbeit auf dem Feld
|  | 23.3 Attribute, Methoden und Konstruktoren
|  |  | 23.3.1 Reflections Gespür für Attribute einer Klasse
|  |  | 23.3.2 Methoden einer Klasse erfragen
|  |  | 23.3.3 Properties einer Bean erfragen
|  |  | 23.3.4 Konstruktoren einer Klasse
|  |  | 23.3.5 Annotationen
|  | 23.4 Objekte erzeugen und manipulieren
|  |  | 23.4.1 Objekte erzeugen
|  |  | 23.4.2 Die Belegung der Variablen erfragen
|  |  | 23.4.3 Eine generische toString()-Funktion
|  |  | 23.4.4 Variablen setzen
|  |  | 23.4.5 Private Attribute ändern
|  | 23.5 Methoden aufrufen
|  |  | 23.5.1 Statische Methoden aufrufen
|  |  | 23.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen
|  | 23.6 Informationen und Identifizierung von Paketen
|  |  | 23.6.1 Geladene Pakete
|  | 23.7 Annotationen
|  |  | 23.7.1 Neue Annotationen definieren
|  |  | 23.7.2 Annotationen mit genau einem Element
|  |  | 23.7.3 Beliebige Schlüssel-Werte-Paare
|  |  | 23.7.4 Vorbelegte Elemente
|  |  | 23.7.5 Annotieren von Annotationstypen
|  |  | 23.7.6 Annotationen zur Laufzeit ausgelesen
|  |  | 23.7.7 Mögliche Nachteile von Annotationen
## 23.5 Methoden aufrufen Nach dem Abfragen und Setzen von Variablenwerten und Konstruktor-Aufrufen zum Erzeugen eines Objekts ist das Aufrufen von Methoden per Reflection der letzte Schritt. Wenn zur Compile-Zeit der Name der Methode nicht feststeht, lässt sich zur Laufzeit dennoch eine im Programm definierte Methode aufrufen, wenn ihr Name als Zeichenkette vorliegt. Zunächst gehen wir wieder von einem Class-Objekt aus, das die Klasse des Objekts beschreibt, für das eine Objektmethode aufgerufen werden soll. Anschließend wird ein Method-Objekt als Beschreibung der gewünschten Methode benötigt; wir bekommen dies mit der Funktion getMethod() aus dem Class-Exemplar. getMethod() verlangt zwei Argumente: einen String mit dem Namen der Methode und ein Array von Class-Objekten. Jedes Element dieses Arrays entspricht einem Parametertyp aus der Signatur der Methode. Damit werden überladene Methoden unterschieden. Nachdem wir das beschreibende Method-Exemplar und die Parameterwerte für den Aufruf vorbereitet haben, ruft invoke() die Zielmethode auf – im Englischen heißt dies dynamic invocation. invoke() erwartet zwei Argumente: ein Array mit Funktionsargumenten, die der aufgerufenen Methode übergeben werden, und eine Referenz auf das Objekt, auf dem die Methode aufgerufen werden soll und zur Auflösung der dynamischen Bindung dient.
    final class java.lang.reflect.Method
    extends AccessibleObject
    implements GenericDeclaration, Member
Object invoke( Object obj, Object... args ) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException Ruft eine Methode des Objekts obj mit den gegebenen Argumenten auf. Wie schon beim Konstruktor löst die Methode eine InvocationTargetException aus, wenn die aufzurufende Funktion eine Exception auslöst.
Beispiel Wir erzeugen ein Point-Objekt und setzen im Konstruktor den x-Wert auf 10. Anschließend fragen wir mit der Methode getX(), die wir dynamisch aufrufen, den x-Wert wieder ab. Listing 23.16 com/tutego/insel/meta/InvokeMethod.java, main()
    Point p = new Point( 10, 0 );
    Method method = p.getClass().getMethod( "getX" );
    String returnType = method.getReturnType().getName();
    Object returnValue = method.invoke( p );
    System.out.printf( "(%s) %s", returnType, returnValue ); // (double) 10.0
Beispiele der Varargs sind bei getMethod() die Parametertypen und bei invoke() die Argumente für setLocation(). Da getMethod() eine beliebige Anzahl von Argumenten annehmen kann und kein Argument dazuzählt, muss die Methode nicht so parametrisiert werden:
    Method method = p.getClass().getMethod( "getX", (Class[]) null );
Auffälliger ist die Möglichkeit der variablen Argumentanzahl bei invoke(). Da ein Getter keine Parameter besitzt, heißt es kurz method.invoke(p); statt wie vor Java 5:
    method.invoke( p, (Object[]) null );
Interessant sind Methoden mit Parameterliste, wie setLocation():
    Point p = new Point();
    Method method = p.getClass().getMethod( "setLocation", int.class, int.class );
    method.invoke( p, 1, 2 );
    System.out.println( p );
### 23.5.1 Statische Methoden aufrufen Wir wollen ein Beispiel programmieren, in dem die Klasse InvokeMain die main()-Funktion einer anderen Klasse, HasMain, mit einem Parameter aufruft. Listing 23.17 com/tutego/insel/meta/InvokeMain.java
    package com.tutego.insel.meta;

    import java.lang.reflect.*;
    import java.util.Arrays;

    public class InvokeMain
    {
      public static void main( String[] args ) throws Exception
      {
        String[] argv = { "-option", "Parameter" };

        Method method = Class.forName( "com.tutego.insel.meta.HasMain" ).
                           getMethod( "main", argv.getClass() );

        method.invoke( null, new Object[]{ argv } );
      }
    }

    class HasMain
    {
      public static void main( String[] args )
      {
        System.out.println( "Got: " + Arrays.toString( args ) );
      }
    }
### 23.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen Werden über Reflection Methoden aufgerufen, deren Funktionsnamen erst zur Laufzeit bestimmt werden, so ist die Geschwindigkeit nicht optimal – auch wenn es seit Java 5 nicht mehr so schlimm ist. (Doch immer noch zeigt eine einfache Zeitmessung einen deutlichen Unterschied.) Diese Aufrufe lassen sich prinzipbedingt auch durch einen JIT-Compiler nicht weiter beschleunigen. Wir müssen also nach einer Lösung suchen, mit der wir diese Art von Aufruf beschleunigen können. Ein möglicher Weg hierbei ist, in Kenntnis des Namens der Methode – nennen wir die Methode meth() – den Namen in einer (abstrakten) Oberklasse dem Compiler bereits bekannt zu machen. Reflection ist nur zum Laden einer Unterklasse mit gegebenem Namen nötig; die normale, dynamische Methodenbindung erledigt den Rest – ganz ohne versteckte Schnüre, doppelte Böden oder Spiegel (Reflection). Versuchen wir, den folgenden Code nach diesem Schema zu ändern: Listing 23.18 com/tutego/insel/meta/DynamReflection.java, main()
    Class<?> clazz = Class.forName("com.tutego.insel.meta.DynamReflectionMethod" );
    Object o = clazz.newInstance();
    clazz.getMethod( "meth" ).invoke( o );
DynamReflection ist die Hauptklasse, die die Klasse DynamReflectionMethod über Class.forName() anfordert. Listing 23.19 com/tutego/insel/meta/DynamReflectionMethod.java
    package com.tutego.insel.meta;

    public class DynamReflectionMethod
    {
      public void meth()
      {
        System.out.println( "Bewusste Raucher trinken Filterkaffee" );
      }
    }
Über das Class-Objekt erzeugt newInstance() ein neues Exemplar. getMethod() sucht die Beschreibung der Methode meth() heraus, und invoke() ruft die Methode »meth« auf. Hier genau liegt ein kleiner Geschwindigkeitsverlust. Wenn es uns gelingen würde, um das invoke() herumzukommen, wäre das schon ein großer Fortschritt. Dies schaffen wir, indem wir eine Schnittstelle (oder Oberklasse) für DynamReflectionMethod konstruieren, die genau diese Methode vorschreibt. Die implementierende Klasse (beziehungsweise Unterklasse) wird dann eine Implementierung angeben. Listing 23.20 com/tutego/insel/meta/DynamAbstract.java
    package com.tutego.insel.meta;

    interface DynamBase
    {
      void meth();
    }

    class DynamBaseMethod implements DynamBase
    {
      public void meth()
      {
        System.out.println( "Bewusste Raucher trinken Filterkaffee" );
      }
    }

    public class DynamAbstract
    {
      public static void main( String[] args ) throws Exception
      {
        Class<?> clazz = Class.forName( "DynamBaseMethod" );
        DynamBase o = (DynamBase) clazz.newInstance();
        o.meth();
      }
    }
DynamBase ist eine Schnittstelle, die zur Übersetzungszeit bekannt ist. Die virtuelle Maschine löst den Aufruf nach den üblichen Regeln der dynamischen Bindung selbst auf. Die Klasse DynamBaseMethod wird ebenfalls erst zur Laufzeit geladen. Wir verstecken hier sehr elegant den Aufwand. Wir haben die gleiche Funktionalität und Flexibilität wie im vorangegangenen Reflection-Beispiel – wenn wir die Möglichkeit, den Klassennamen durch einen String anzugeben, außer Acht lassen –, aber mit der höheren Geschwindigkeit eines konventionellen Methodenaufrufs ohne Reflection. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.
Name |
E-Mail |
Ihr Kommentar |
<< zurück | <top> | vor >>

Copyright © Galileo Press 2008
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