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 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?

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

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
Pfeil 23 Reflection und Annotationen
Pfeil 23.1 Metadaten
Pfeil 23.1.1 Metadaten durch Java-Doc Tags
Pfeil 23.1.2 XDoclet
Pfeil 23.2 Metadaten der Klassen mit dem Class-Objekt
Pfeil 23.2.1 An ein Class-Objekt kommen
Pfeil 23.2.2 Was das Class-Objekt beschreibt
Pfeil 23.2.3 Der Name der Klasse
Pfeil 23.2.4 instanceof mit Class-Objekten
Pfeil 23.2.5 Oberklassen finden
Pfeil 23.2.6 Implementierte Interfaces einer Klasse oder eines Interfaces
Pfeil 23.2.7 Modifizierer und die Klasse Modifier
Pfeil 23.2.8 Die Arbeit auf dem Feld
Pfeil 23.3 Attribute, Methoden und Konstruktoren
Pfeil 23.3.1 Reflections Gespür für Attribute einer Klasse
Pfeil 23.3.2 Methoden einer Klasse erfragen
Pfeil 23.3.3 Properties einer Bean erfragen
Pfeil 23.3.4 Konstruktoren einer Klasse
Pfeil 23.3.5 Annotationen
Pfeil 23.4 Objekte erzeugen und manipulieren
Pfeil 23.4.1 Objekte erzeugen
Pfeil 23.4.2 Die Belegung der Variablen erfragen
Pfeil 23.4.3 Eine generische toString()-Funktion
Pfeil 23.4.4 Variablen setzen
Pfeil 23.4.5 Private Attribute ändern
Pfeil 23.5 Methoden aufrufen
Pfeil 23.5.1 Statische Methoden aufrufen
Pfeil 23.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen
Pfeil 23.6 Informationen und Identifizierung von Paketen
Pfeil 23.6.1 Geladene Pakete
Pfeil 23.7 Annotationen
Pfeil 23.7.1 Neue Annotationen definieren
Pfeil 23.7.2 Annotationen mit genau einem Element
Pfeil 23.7.3 Beliebige Schlüssel-Werte-Paare
Pfeil 23.7.4 Vorbelegte Elemente
Pfeil 23.7.5 Annotieren von Annotationstypen
Pfeil 23.7.6 Annotationen zur Laufzeit ausgelesen
Pfeil 23.7.7 Mögliche Nachteile von Annotationen


Galileo Computing - Zum Seitenanfang

23.5 Methoden aufrufen Zur nächsten ÜberschriftZur vorigen Überschrift

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

Galileo Computing - Zum Seitenanfang

23.5.1 Statische Methoden aufrufen Zur nächsten ÜberschriftZur vorigen Überschrift

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

Galileo Computing - Zum Seitenanfang

23.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen topZur vorigen Überschrift

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.






<< zurück



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