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.6 Annotationen Zur nächsten ÜberschriftZur vorigen Überschrift

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.


Galileo Computing - Zum Seitenanfang

24.6.1 Neue Annotationen definieren Zur nächsten ÜberschriftZur vorigen Überschrift

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 { }


Galileo Computing - Zum Seitenanfang

24.6.2 Annotationen mit genau einem Element Zur nächsten ÜberschriftZur vorigen Überschrift

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

Galileo Computing - Zum Seitenanfang

24.6.3 Beliebige Schlüssel-Werte-Paare Zur nächsten ÜberschriftZur vorigen Überschrift

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


Galileo Computing - Zum Seitenanfang

24.6.4 Vorbelegte Elemente Zur nächsten ÜberschriftZur vorigen Überschrift

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.


Galileo Computing - Zum Seitenanfang

24.6.5 Annotieren von Annotationstypen Zur nächsten ÜberschriftZur vorigen Überschrift

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


Galileo Computing - Zum Seitenanfang

24.6.6 Annotationen zur Laufzeit auslesen Zur nächsten ÜberschriftZur vorigen Überschrift

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.Zeilen-Umbruch  class) );    // true 
 DatabaseDAO.class.isAnnotationPresent(Documented.Zeilen-Umbruch  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.


Galileo Computing - Zum Seitenanfang

24.6.7 Mögliche Nachteile von Annotationen Zur nächsten ÜberschriftZur vorigen Überschrift

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.


Galileo Computing - Zum Seitenanfang

24.6.8 XDoclet topZur vorigen Überschrift

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.






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