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

Die vordefinierten Annotationen haben eine besondere Semantik, wie @Override oder @SuppressWarning 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

23.7.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 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 Beispiel Annotiere eine Klasse:

@Optimize 
public class DatabaseDAO { }


Galileo Computing - Zum Seitenanfang

23.7.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 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 primitive 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 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()                  // Fehler 
@Optimize(1)                 // Fehler 
@Optimize("Wichtig: " + 1)   // OK 
@Optimize(null)              // Fehler

Galileo Computing - Zum Seitenanfang

23.7.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 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 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 Element-Typen 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 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 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-Anweisung 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 Element-Typ 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 Element-Typen erlaubt sind. Die Annotation als Element-Typ löst dies auf schöne Weise.


Beispiel Beispiel Ein Annotationstyp Name soll Vor- und Nachname speichern:

Listing 23.21 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 23.22 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

23.7.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 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 Element-Typen 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

23.7.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 23.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 Laufzeitumgebung?

@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 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 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 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 Beispiel @Documented ist selbst @Documented:

@Documented 
@Target( value=ANNOTATION_TYPE ) 
public @interface Documented


Galileo Computing - Zum Seitenanfang

23.7.6 Annotationen zur Laufzeit ausgelesen 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 Beispiel Eine mit @Optimize versehene Annotation soll zur Laufzeit erfragbar sein.

Listing 23.23 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 Klasse Class, Constructor, Field, Method, Package und AccessibleObject folgende Methoden 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 Beispiel Die Klasse DatabaseDAO ist nur mit @Optimize annotiert.

System.out.println( DatabaseDAO.class.isAnnotationPresent(Optimize.class) ); 
                                                                        // true 
System.out.println( 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 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 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])

Völlig generisch lassen sich von der Annotationsschnittstelle die Methoden 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 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 Beispiel Teste die Annotationen auf einem Class-Objekt clazz. Im Fall der Optimize-Annotation sollen die drei assoziierten Elemente ausgegeben werden:

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

23.7.7 Mögliche Nachteile von Annotationen topZur 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 nicht mitunter 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.



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