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?
<< zurück | Galileo Computing / <openbook> / Java-Insel | vor >>
Java ist auch eine Insel (8. Auflage) von Christian Ullenboom Programmieren mit der Java Standard Edition Version 6
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 |
| 24 Reflection und Annotationen
|  | 24.1 Metadaten
|  |  | 24.1.1 Metadaten durch JavaDoc-Tags
|  | 24.2 Metadaten der Klassen mit dem Class-Objekt
|  |  | 24.2.1 An ein Class-Objekt kommen
|  |  | 24.2.2 Was das Class-Objekt beschreibt
|  |  | 24.2.3 Der Name der Klasse
|  |  | 24.2.4 instanceof mit Class-Objekten
|  |  | 24.2.5 Oberklassen finden
|  |  | 24.2.6 Implementierte Interfaces einer Klasse oder eines Interfaces
|  |  | 24.2.7 Modifizierer und die Klasse Modifier
|  |  | 24.2.8 Die Arbeit auf dem Feld
|  | 24.3 Attribute, Methoden und Konstruktoren
|  |  | 24.3.1 Reflections – Gespür für Attribute einer Klasse
|  |  | 24.3.2 Methoden einer Klasse erfragen
|  |  | 24.3.3 Properties einer Bean erfragen
|  |  | 24.3.4 Konstruktoren einer Klasse
|  |  | 24.3.5 Annotationen
|  | 24.4 Objekte erzeugen und manipulieren
|  |  | 24.4.1 Objekte erzeugen
|  |  | 24.4.2 Die Belegung der Variablen erfragen
|  |  | 24.4.3 Eine generische toString()-Funktion
|  |  | 24.4.4 Variablen setzen
|  |  | 24.4.5 Private Attribute ändern
|  | 24.5 Methoden aufrufen
|  |  | 24.5.1 Statische Methoden aufrufen
|  |  | 24.5.2 Dynamische Methodenaufrufe bei festen Methoden beschleunigen
|  | 24.6 Annotationen
|  |  | 24.6.1 Neue Annotationen definieren
|  |  | 24.6.2 Annotationen mit genau einem Element
|  |  | 24.6.3 Beliebige Schlüssel-Werte-Paare
|  |  | 24.6.4 Vorbelegte Elemente
|  |  | 24.6.5 Annotieren von Annotationstypen
|  |  | 24.6.6 Annotationen zur Laufzeit auslesen
|  |  | 24.6.7 Mögliche Nachteile von Annotationen
|  |  | 24.6.8 XDoclet
|  | 24.7 Zum Weiterlesen
## 24.6 Annotationen Die vordefinierten Annotationen haben eine besondere Semantik, wie @Override oder @SuppressWarnings gut zeigen. Anders als die von Sun definierten JavaDoc-Tags für die API-Dokumentation lassen sich ganz selbstverständlich eigene Annotationstypen definieren. Neue Frameworks wie EJB 3 oder Bibliotheken wie Web-Services machen davon fleißig Gebrauch, wie schon unser eingehendes Beispiel mit dem Annotationstyp @WebMethod zeigte. ### 24.6.1 Neue Annotationen definieren Ein Annotationstyp (engl. annotation type) wird so definiert wie eine Schnittstelle, nur steht vor dem Schlüsselwort interface ein @-Zeichen. Die Deklaration von neuen Annotationstypen und Schnittstellen ist so groß, dass in der Java Language Specification die Annotationen auch im Kapitel über Schnittstellen behandelt werden. (Später erfahren wir den Grund dafür: Der Compiler übersetzt die Annotationstypen in Schnittstellen.)
Beispiel Um Elemente zur späteren Optimierung zu markieren, soll ein neuer Annotationstyp Optimize entworfen werden:
    public @interface Optimize
    {
    }
Unseren neuen Annotationstyp können wir nun an beliebigen Typdeklarationen (Objekt-/Klassen-/lokale Variablen, Parameter), Methoden oder Konstruktoren festmachen.
Beispiel Annotiere eine Klasse:
    @Optimize
    public class DatabaseDAO { }
### 24.6.2 Annotationen mit genau einem Element Der Annotationstyp konnte mit keinem zusätzlichen Annotationselement versehen werden, da er in der bisherigen Schreibweise eine Markierungsannotation ist. Erlaubt sind zwar ein Paar runde Klammern hinter dem Namen und auch Kommentare, aber eben kein Wert.
    @Optimize class DatabaseDAO                   // OK
    @Optimize() class DatabaseDAO                 // OK
    @Optimize("Schneller!") class DatabaseDAO     // Compilerfehler
Damit zusätzliche Informationen wie im dritten Beispiel erlaubt sind, werden im Annotationstyp Deklarationen eingesetzt, deren Schreibweise an Operationen in einer Java-Schnittstelle erinnert. (Aber die Methoden dürfen keinen Parameter definieren, die Rückgabe darf nicht void sein und kein throws besitzen.)
Beispiel Der Annotationstyp Optimize muss mit einem String versehen werden:
    public @interface Optimize
    {
      String value();
    }
Der Rückgabetyp der Methode bestimmt den Typ des Annotationselements und ist im begrenzten Rahmen wählbar. Insgesamt erlaubt die Deklaration: alle primitiven Datentypen (byte, short, int, long, float, double, boolean), aber keine Wrapper String Class (inklusive Typ) Enum-Typen andere Annotationen (was zu geschachtelten Annotationen führt) Felder von oben genannten Typen. Felder von Feldern (mehrdimensionale Felder) sind aber nicht gestattet. Elemente, die so heißen wie die Methoden aus Object, sind nicht zugelassen.
Beispiel Nutze den Annotationstyp Optimize:
    @Optimize( "Schneller!" )
    public class DatabaseDao
    {
    }
Die Elemente sind typisiert, und notwendige Typkonvertierungen führt der Compiler automatisch durch. null ist als Argument nie erlaubt. Fehlt das erwartete Element, gibt es einen Compilerfehler.
    @Optimize( "Schneller!" )      // OK
    @Optimize()                    // Compilerfehler
    @Optimize( 1 )                 // Compilerfehler
    @Optimize( "Wichtig: " + 1 )   // OK
    @Optimize( null )              // Compilerfehler
### 24.6.3 Beliebige Schlüssel-Werte-Paare Wenn der Annotationstyp ein Element value definiert, so muss keine Angabe über einen Schlüsselnamen gemacht werden, obwohl das möglich ist und schon das erste Beispiel für ein Schlüssel-Werte-Paar darstellt:
    @Optimize( value = "Schneller!" )
Eine Annotation lässt sich mit einer beliebigen Anzahl von Elementen definieren, und value ist nur dann nötig, wenn der Schlüssel nicht ausdrücklich genannt werden soll. Ist mehr als ein Element definiert, muss ohnehin der Elementname zusammen mit der Belegung genannt werden, und value könnte auch anders heißen.
Beispiel Der Annotationstyp Optimize soll zusätzlich zur Aufgabe auch diejenige Person speichern, die die Aufgabe erledigen soll:
    public @interface Optimize
    {
      String value();
      String assignedTo();
    }
Und in der Anwendung:
    @Optimize( value = "schneller", assignedTo = "Christian" )
    public class DatabaseDAO
    {
    }
#### Unterschiedliche Typen der Elemente String ist ein häufiger Datentyp für Elemente, doch auch die primitiven Datentypen – neben einigen anderen – sind erlaubt. Dazu einige Beispiele.
Beispiel Die Optimierung hat eine bestimmte Priorität. Sie soll als int angegeben werden:
    public @interface Optimize
    {
      String value();
      String assignedTo();
      int    priority();
    }
In unserem Beispiel soll sie 5 sein:
    @Optimize(
        value      = "schneller",
        assignedTo = "Christian",
        priority   = 5 )
#### Felder von Annotationselementen Von den unterschiedlichen Elementtypen dürfen eindimensionale Felder gebildet werden. Da es keine anderen Sammlungen gibt, stellt das Feld die einzige Möglichkeit dar, beliebig viele Elemente anzugeben.
Beispiel Die Optimierungaufgabe soll nicht nur einer Person zugewiesen werden können, sondern mehreren. assignedTo muss ein Feld vom Typ String werden.
    public @interface Optimize
    {
      String   value();
      String[] assignedTo();
      int      priority();
    }
Interessanterweise muss die Zeile mit der Zuweisung an assignedTo nicht geändert werden, denn bei nur einem Element kann die Zuweisung so bleiben.
    @Optimize(
        value      = "schneller",
        assignedTo = "Christian",
        priority   = 5 )
Mehrere Elemente kommen in ein geschweiftes Klammernpaar:
        assignedTo = { "Christian", "Jens" },
Für ein leeres Feld bleibt nur ein Klammernpaar:
        assignedTo = { },
Neben Feldern sind Aufzählungen sehr nützlich. Sie machen Ganzzahlen als magische Zahlen für Konstanten überflüssig. #### Annotationselemente als Aufzählungen Definiert der Annotationstyp ein Element vom Typ einer Aufzählung, so kann die Enum jede bekannte Aufzählung sein. Möglich ist auch, die Aufzählung innerhalb von @interface als inneren Typ zu definieren. Das ist besonders interessant, wenn die Aufzählung nicht allgemein ist, sondern ausschließlich Sinn mit einer Annotation ergibt.
Beispiel Die Priorität soll keine Ganzzahl, sondern eine innere Aufzählung sein.
    public @interface Optimize
    {
      enum Priority { LOW, NORM, HIGH }

      String   value();
      String[] assignedTo();
      Priority priority();
    }
Der innere Typ Priority ist über den äußeren Typ Optimize anzusprechen:
    @Optimize(
        value      = "schneller",
        assignedTo = "Christian",
        priority   = Optimize.Priority.HIGH )
Ist die Qualifizierung über die äußere Klasse nicht erwünscht, so ist eine import-Deklaration zu setzen. Etwa so:
    import com.tutego.insel.annotation.Optimize.Priority;
Das erlaubt priority = Priority.HIGH. Um auch noch Priority. einzusparen, muss ein statisches import gesetzt werden.
Der Elementtyp Class ist selten anzutreffen, doch mit den generischen Einschränkungen ermöglicht er eine präzise Klassenangabe. Häufiger ist hingegen eine Annotation in der Annotation zu finden, vor allem, weil keine beliebigen Typen als Elementtypen erlaubt sind. Die Annotation als Elementtyp löst dies auf schöne Weise.
Beispiel Ein Annotationstyp Name soll Vor- und Nachname speichern: Listing 24.22 com/tutego/insel/annotation/Name.java
    package com.tutego.insel.annotation;

    public @interface Name
    {
      String firstname();
      String lastname();
    }
Der Annotationstyp Author nutzt Name als Elementtyp für value: Listing 24.23 com/tutego/insel/annotation/Author.java
    package com.tutego.insel.annotation;

    public @interface Author
    {
      Name[] value();
    }
Vor Name steht nicht das @-Zeichen. Nur in der Anwendung:
    @Author( @Name( firstname = "Christian", lastname = "Ullenboom" ) )
Hätten wir das Element nicht value, sondern etwa name genannt, müsste die Angabe so heißen:
    name = @Name( firstname = "Christian", lastname = "Ullenboom" )
Und hätten wir mehrere Autoren, sprich Namen, angegeben, würden wir Folgendes schreiben:
    @Author(
      {
        @Name(firstname="Christian", lastname="Ullenboom"),
        @Name(firstname="Hansi", lastname="Hinterweltler")
      } )
### 24.6.4 Vorbelegte Elemente Im bisherigen Fall mussten alle Werte angegeben werden, und wir konnten kein Schlüssel-Werte-Paar auslassen. Die Annotationstypen ermöglichen allerdings für Elemente Standardwerte, sodass ein Wert angeben werden kann, aber nicht muss. In der Syntax hält dafür das default her, was auch zu einer neuen Schreibweise führt, die von den Schnittstellen abweicht.
Beispiel Für den Annotationstyp Optimize sollen der Bearbeiter und die Priorität auf Standardwerte gesetzt werden.
    package com.tutego.insel.annotation;

    public @interface Optimize
    {
      enum Priority { LOW, NORM, HIGH }

      String   value();
      String[] assignedTo() default "";
      Priority priority()   default Priority.NORM;
    }
#### Nachträgliche Änderung und die Sinnhaftigkeit von Standardwerten Standardwerte sind für Annotationen ein sehr wichtiges Instrument, denn wenn einmal eine Annotation definiert wurde, ist eine Änderung nicht immer möglich; das Phänomen ist von Schnittstellen hinlänglich bekannt. Neben dem Hinzufügen neuer Elemente stellt bei Schnittstellen das Löschen von Operationen kein Problem dar – ganz im Unterschied zu Annotationen: Werden Elemente entfernt, gibt es Compilerfehler. Auch das Ändern von Elementtypen führt im Allgemeinen zu Compilerfehlern. Werden neue Elemente in bestehende Annotationstypen eingefügt, dann müssten alle existierenden konkreten Annotationen das neue Element setzen, was eine sehr große Änderung ist, vergleichbar einem neuen Element in einer Schnittstelle. Anders als bei Schnittstellen lösen Default-Werte das Problem, da auf diese Weise für das neue Element immer gleich ein Wert vorhanden ist, der, sofern erwünscht, neu belegt werden kann. Ohne Probleme ist es möglich, einen Default-Wert hinzuzunehmen, während das Entfernen von Standardwerten kritisch ist. ### 24.6.5 Annotieren von Annotationstypen Von den in Java 5 eingeführten Annotationen haben wir die drei Typen aus dem Paket java.lang schon kennengelernt. Die restlichen vier Annotationen aus dem Paket java.lang.annotation dienen dazu, Annotationstypen zu annotieren. In diesem Fall wird von Meta-Annotationen gesprochen.

Tabelle 24.2 Meta-Annotationen

@Target | Was lässt sich annotieren? Klasse, Methode ...?
@Retention | Wo ist die Annotation sichtbar? Nur für den Compiler oder auch für die Laufzeit-umgebung?
@Documented | Zeigt den Wunsch an, die Annotation in der Dokumentation zu erwähnen.
@Inherited | Macht deutlich, dass ein annotiertes Element auch in der Unterklasse annotiert ist.
#### @Target Die Annotation @Target definiert, wo eine Annotation angeheftet werden kann. Die Aufzählung java.lang.annotation.ElementType definiert dazu die folgenden Ziele: ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE Ist kein ausdrückliches @Target gewählt, gilt es für alle Elemente.
Beispiel Unsere Annotation Optimize soll vor beliebigen Typen, Methoden, Paketen und Konstruktoren erlaubt sein:
    package com.tutego.insel.annotation;

    import java.lang.annotation.Target;
    import static java.lang.annotation.ElementType.*;

    @Target( { TYPE, METHOD, CONSTRUCTOR, PACKAGE } )
    public @interface Optimize
    {
      ...
    }
Das erste import macht den Annotationstyp Target dem Compiler bekannt, und das zweite statische import macht die Aufzählung ElementType zugänglich.
Mit ElementType.TYPE ist die Annotation vor allen Typen – Klassen, Schnittstellen, Annotationen, Enums – erlaubt. Eine Einschränkung, etwa nur auf Klassen, ist nicht möglich. Interessant ist die Tatsache, dass eine Unterteilung für Methoden und Konstruktoren möglich ist und sogar lokale Variablen annotiert werden können.
Beispiel Beim existierenden Annotationstyp @Overrides ist die Annotation @Target schön zu erkennen.
    @Target( value=METHOD )
    public @interface Overrides
Die Idee der Meta-Annotation: Es gibt nur überschriebene Methoden.
#### @Retention Die Annotation @Retention steuert, wer die Annotation sehen kann. Es gibt drei Typen, die in der Aufzählung java.lang.annotation.RetentionPolicy genannt sind: SOURCE. Vom Compiler verworfen. Nützlich für Tools. CLASS. Abgebildet in der Klassendatei, aber von der JVM ignoriert. RUNTIME. Annotation wird gespeichert und ist für die JVM verfügbar. Die Unterscheidung haben die Java-Designer vorgesehen, da nicht automatisch jede Annotation zur Laufzeit verfügbar ist. (Eine Begründung: Andernfalls würde es den Ressourcenverbrauch erhöhen.) Der Standard ist RetentionPolicy.CLASS.
Beispiel Der Annotationstyp @Deprecated ist nur für den Compiler und nicht für die Laufzeit von Interesse:
    @Retention( value=SOURCE )
    public @interface Deprecated
Ist ein Element mit @Target annotiertet, so soll diese Information auch zur Laufzeit vorliegen:
    @Retention( value=RUNTIME )
    @Target( value=ANNOTATION_TYPE )
    public @interface Target
Das Beispiel zeigt, dass die Anwendung auch rekursiv sein kann (natürlich auch indirekt rekursiv, denn nicht nur @Retention annotiert @Target, auch @Target annotiert @Retention).
#### @Documented Die Annotation @Documented zeigt an, dass die Annotation in der API-Dokumentation genannt werden soll. Alle Standard-Annotationen von Java werden so angezeigt, auch @Documented selbst. In der API-Dokumentation ist für die Annotationen ein neues Segment definiert.
Beispiel @Documented ist selbst @Documented:
    @Documented
    @Target( value=ANNOTATION_TYPE )
    public @interface Documented
### 24.6.6 Annotationen zur Laufzeit auslesen Sollen Annotationen zur Laufzeit ausgelesen werden, so muss die @Retention mit RetentionPolicy.RUNTIME gesetzt sein. Damit ist unser Beispiel für den Annotationstyp vollständig:
Beispiel Eine mit @Optimize versehene Annotation soll zur Laufzeit erfragbar sein. Listing 24.24 com/tutego/insel/annotation/Optimize.java
    package com.tutego.insel.annotation;

    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    @Target( { TYPE, METHOD, CONSTRUCTOR, PACKAGE } )
    @Retention( RetentionPolicy.RUNTIME )
    public @interface Optimize
    {
      enum Priority { LOW, NORM, HIGH }

      String   value();
      String[] assignedTo() default "";
      Priority priority()   default Priority.NORM;
    }
Da nun unterschiedliche Dinge annotierbar sind, schreibt eine Schnittstelle AnnotatedElement für die Klassen Class, Constructor, Field, Method, Package und AccessibleObject folgende Operationen vor:
    interface java.lang.reflect.AnnotatedElement
<T extends Annotation> T getAnnotation( Class<T> annotationType ) Liefert die Annotation für einen bestimmten Typ. Ist sie nicht vorhanden, dann ist die Rückgabe null. boolean isAnnotationPresent( Class<? extends Annotation> annotationType ) Gibt es die angegebene Annotation? Annotation[] getAnnotations() Liefert die an dem Element festgemachten Annotationen. Gibt es keine Annotation, ist das Feld leer. Die Methode liefert auch Annotationen, die aus den Oberklassen kommen. Annotation[] getDeclaredAnnotations() Liefert die Annotationen, die exakt an diesem Element festgemacht sind.
Beispiel Die Klasse DatabaseDAO ist nur mit @Optimize annotiert.
     DatabaseDAO.class.isAnnotationPresent(Optimize.  class) );    // true
     DatabaseDAO.class.isAnnotationPresent(Documented.  class) );    // false
Um auf die einzelnen Elemente einer Annotation zuzugreifen, müssen wir etwas mehr über die Umsetzung einer Annotation von Compiler und der JVM wissen. Übersetzt der Compiler einen Annotationstyp, generiert er daraus eine Schnittstelle.
Beispiel Für den Annotationstyp Optimize generiert der Compiler:
    public interface Optimize extends java.lang.annotation.Annotation
    {
      public static final class Priority extends Enum { ... }
      String value();
      String[] assignedTo();
      Priority priority();
    }
Zur Laufzeit werden über java.lang.reflect.Proxy die Klassen gebaut, die die Annotationen repräsentieren. Rufen wir auf einem AnnotatedElement eine Methode wie getAnnotation() auf, bekommen wir das Proxy-Objekt, das vom Typ der Schnittstelle java.lang.annotation.Annotation ist.
Beispiel Nutzen wir die Methode getAnnotations() vom DatabaseDAO.class-Objekt, bekommen wir das Proxy-Objekt, das in der toString()-Methode die Werte zeigt:
    for ( Annotation a : Optimize.class.getAnnotations() )
     out.println( a ); // @com.tutego.insel.annotation.Optimize(assignedTo=[Christian],
                       priority=HIGH, value=Schneller!)
Default-Werte werden zur Laufzeit gesetzt. Eine Schleife über Documented.class.getAnnotations() liefert:
    @java.lang.annotation.Documented()
    @java.lang.annotation.Retention(value=RUNTIME)
    @java.lang.annotation.Target(value=[ANNOTATION_TYPE])
Zwar lassen sich völlig generisch alle Annotationen eines Typs aufzählen, doch im Allgemeinen dürfte der erwartete Typ bekannt sein. Die Typisierung von getAnnotation() ist dabei besonders hilfreich. Zur Wiederholung: <A extends Annotation> A getAnnotation( Class<A> annotationClass ) Das Argument ist ein Class-Objekt, das den Annotationstyp repräsentiert. Die Rückgabe ist genau die konkrete Annotation für das annotierte Element.
Beispiel Die typisierte getAnnotation() liefert ein konkretes Annotationsobjekt:
    Optimize annotation = DatabaseDAO.class.getAnnotation(Optimize.class);
    System.out.println( annotation.value() );  // Schneller!
Die anderen Methoden getAnnotations() und getDeclaredAnnotations() liefern nicht so präzise Typen und nur ein Feld von Annotation-Objekten; hier muss eine Typanpassung beim Auslesen helfen.
Beispiel Teste die Annotationen auf einem Class-Objekt clazz. Im Fall der Optimize-Annotation sollen die drei assoziierten Elemente ausgegeben werden: Listing 24.25 com/tutego/insel/annotation/ReadAnnotations.java
    for ( Annotation a : clazz.getAnnotations() )
      if ( a instanceof Optimize )
      {
        Optimize oa = (Optimize) a;

        out.println( oa.value() );                       // Schneller!
        out.println( Arrays.toString(oa.assignedTo()) ); // [Christian]
        out.println( oa.priority() );                    // HIGH
      }
Die Annotation ist zur Laufzeit ein Proxy-Objekt und kann keine eigene Klasse erweitern und auch keine anderen eigenen Schnittstellen implementieren. Eine Annotation kann auch keine andere Annotation erweitern. Es könnte eine eigene Klasse zwar die Schnittstelle java.lang.annotation.Annotation implementieren, doch entsteht dadurch keine echte Annotation, was eine eigene Implementierung sinnlos macht. ### 24.6.7 Mögliche Nachteile von Annotationen Annotationen sind eine gewaltige Neuerung und sicherlich die wichtigste seit vielen Java-Jahren. Auch wenn die Generics auf den ersten Blick bedeutsam erscheinen, sind die Annotationen ein ganz neuer Schritt in die deklarative Programmierung, wie sie Frameworks schon heute aufzeigen. Völlig problemlos sind Annotationen allerdings nicht: Die Annotationen sind stark mit dem Quellcode verbunden, können also auch nur dort geändert werden. Ist der Original-Quellcode nicht verfügbar, etwa weil der Auftraggeber ihn geschlossen hält, ist eine Änderung der Werte nahezu unmöglich. Wenn Annotationen allerdings nach der Übersetzung nicht mehr geändert werden können, stellt das bei externen Konfigurationsdateien kein Problem dar. Externe Konfigurationsdateien können ebenso den Vorteil bieten, dass die relevanten Informationen auf einen Blick erfassbar sind und sich mitunter nicht redundant auf unterschiedliche Java-Klassen verteilen. Klassen mit Annotationen sind invasiv und binden auch die Implementierungen an einen gewissen Typ, wie es Schnittstellen tun. Sind die Annotationstypen nicht im Klassenpfad, kommt es zu einem Compilerfehler. Bisher gibt es keine Vererbung von Annotationen: Ein Annotationstyp kann keinen anderen Annotationstyp erweitern. Die bei den Annotationen gesetzten Werte lassen sich zur Laufzeit erfragen, aber nicht modifizieren. Warum werden Annotationen mit @interface deklariert, einer Schreibweise, die in Java sonst völlig unbekannt ist? Ein Problem gibt es allerdings nur bei finalen statischen Variablen (Konstanten), das bei den Default-Werten der Annotationen nicht vorkommt: Weil die Default-Werte zur Laufzeit gesetzt werden, lassen sie sich in der Deklaration vom Annotationstyp leicht ändern, und eine Neuübersetzung des Projekts kann somit unterbleiben. ### 24.6.8 XDoclet Das Eingangsbeispiel zeigte anhand von JavaDoc, wie die Dokumentation als Metadaten mit den Quellen verbunden wird. Mit einem JavaDoc-Beispiel soll das Kapitel auch enden. Als von Java 5 und Annotationen noch nichts zu sehen war, haben sich benutzerdefinierte JavaDoc-Tags als sehr flexibel erwiesen. Zwar belegt Sun einige Tags mit bestimmten Bedeutungen (@see, @author ...), doch können Tags in den Dokumentationskommentaren im Prinzip frei gewählt werden. Ein Doclet muss nicht nur HTML generieren, sondern könnte ebenso neue Quellcode- oder XML-Dateien erzeugen oder Tests durchführen, ob Methodennamen gut gewählt sind. Zunutze macht sich das etwa das Programmpaket XDoclet (http://xdoclet.sourceforge.net/). Es generiert aus JavaDoc-Tags Schnittstellen, Hilfsklassen, Deskriptoren und mehr. Häufig anzutreffen ist es bei Enterprise JavaBeans, aber auch bei OR-Mapping oder Servlets. Eine Session-Bean ist nach der Java Enterprise Edition 1.4 in wenigen Zeilen definiert:
    import javax.ejb.SessionBean;

    /**
     * @ejb.bean name = "Hallo"
     *           type = "Stateless"
     *
     **/
    public abstract class HalloBean implements SessionBean
    {
      /**
       * @ejb.interface-method
       */
      public String hallo( String name ) {
        return "Hallo " + name;
      }
    }
Ein Ant-Tag nimmt den so annotierten Quellcode und generiert über ein Doclet alle für die Enterprise JavaBeans nötigen Dateien. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück | <top> | vor >>
Zum Katalog
Java ist auch eine Insel Jetzt bestellen
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Tipp
| Coding for Fun
Buchempfehlungen
| Objektorientierte Programmierung
| Einstieg in Eclipse 3.4
| Java 6 lernen mit Eclipse
| NetBeans Platform 6
| Java und XML
| Visual C# 2008
| IT-Handbuch für Fachinformatiker
| C++ von A bis Z
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

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