Annotations (ab Java 5)

+ andere TechDocs
+ Enums
+ Generics
+


Zu den Neuerungen in Java 5 gehören Annotations. Der JSR 175 beschreibt Annotations als "Metadata Facility for the Java Programming Language".

Annotationen beinhalten Metadaten, also Daten über andere Daten. Zu vielen Java-Programmelementen können Annotationen hinzugefügt werden, die während des Build-Vorgangs oder auch zur Laufzeit ausgewertet werden können.



Inhalt

  1. Annotationen vor Java 5 und ab Java 5
  2. Annotation-Kategorien
  3. Meta-Annotationen, Sichtbarkeit, annotierbare Programmelemente
  4. Annotation selbst deklarieren, anwenden und zur Laufzeit auslesen
  5. Erläuterungen zu einigen ausgewählten Java-SE- und Java-EE-Annotationen
  6. Listen der Annotationen in Java SE und Java EE



Annotationen vor Java 5 und ab Java 5

Auch vor Java 5 gab es bereits Annotationen-ähnliche Metadaten:

   /**
    * @deprecated
    * @see #meineNeueMethode
    */
   void meineVeralteteMethode()
   {
      ...
   }

Vor Java 5 mussten Annotationen-ähnliche Metadaten zum Beispiel in JavaDoc-Kommentaren untergebracht werden. Einige wurden vom Compiler ausgewertet (z.B. @deprecated). Andere wurden durch Zusatztools ausgewertet (z.B. mit XDoclet).

Das gleiche Beispiel sieht mit der neuen Java-5-@Deprecated-Annotation folgendermaßen aus:

   /**
    * @see #meineNeueMethode
    */
   @Deprecated
   void meineVeralteteMethode()
   {
      ...
   }

Java-5-Annotationen beginnen mit dem '@'-Zeichen und werden vor dem Programmelement, auf das sie sich beziehen, plaziert, üblicherweise vor den anderen Modifizierern (public, static, final, abstract, void, ...).



Annotation-Kategorien

Es gibt drei Annotation-Kategorien:

Kategorie Erläuterung Beispiele für Anwendung und Deklaration
Marker Annotation Es wird kein Parameter übergeben.
Die Annotation dient zur Markierung.
Beispiele:
@Deprecated, @Override
// Anwendung: 
   @MyAnnotation
// Deklaration:
  
   public @interface MyAnnotation {}
Single Member Annotation Eine Annotation mit nur einem Parameter.
Dieser Parameter hat den Parameternamen "
value", der aber beim Annotieren nicht angegeben werden muss.
Falls für den Parameter ein Defaultwert definiert ist, kann die Annotation auch ohne Parameter verwendet werden.
Der eine Parameter kann ein Array von mehreren Parametern sein.
Beispiele:
@Retention, @Target
// Anwendung:  
   @MyAnnot( myValue )
// Deklaration:
  
   public @interface MyAnnot {
      String value();
   }

Normal Annotation Eine Annotation mit möglicherweise mehreren Parametern.
Den Parametern muss jeweils der Parametername vorangestellt werden. Alle Parameter, für die die Deklaration keinen Defaultwert vorsieht, müssen gesetzt werden.
Beispiele:
@MeineNeueAnnotation, @Resource
// Anwendung:  
   @MyAnnot( prm1=val1, prm2=val2 )
// Deklaration:
  
   public @interface MyAnnot {
      double prm1();
      String prm2();
   }



Meta-Annotationen, Sichtbarkeit, annotierbare Programmelemente

Meta-Annotationen sind Annotationen, die auf Annotationen angewendet werden können. Einige Meta-Annotationen können sowohl auf Annotationen als auch auf andere Programmelemente angewendet werden, andere nur ausschließlich auf Annotationen.

Ein Softwareentwickler, der normalerweise nur bestehende Annotationen anwendet, wird nicht direkt Meta-Annotationen verwenden. Trotzdem muss er sie kennen, um die Deklaration der Java-Annotationen, die er anwenden will, zu verstehen.

Die beiden folgenden besonders wichtigen Meta-Annotationen können nur ausschließlich auf Annotationen angewendet werden:

@Retention @Retention (übersetzt "Bewahrung") steuert die Beibehaltung und Verfügbarkeit der Annotation-Informationen, also wie lange die Annotation-Informationen erhalten bleiben.
Dazu wird einer der folgenden Werte übergeben (Beispiel folgt weiter unten):
RetentionPolicy.SOURCE Nach der Kompilierung stehen die Annotation-Informationen nicht mehr zur Verfügung.
RetentionPolicy.CLASS Die Annotation-Informationen stehen in der .class-Datei noch zur Verfügung, aber nicht mehr zur Laufzeit (Default).
RetentionPolicy.RUNTIME Die Annotation-Informationen stehen auch zur Laufzeit noch zur Verfügung.
@Target @Target (übersetzt "Ziel") steuert welche Programmelemente annotiert werden können.
Dazu wird einer oder mehrere der folgenden Werte übergeben:
ElementType.ANNOTATION_TYPE Annotation
ElementType.TYPE Klasse, Interface (inklusive Annotation), Enum
ElementType.CONSTRUCTOR Konstruktor
ElementType.METHOD Methode
ElementType.FIELD Attribut
ElementType.LOCAL_VARIABLE Lokale Variable
ElementType.PARAMETER Parameter
ElementType.PACKAGE Package (über package-info.java)


Annotation selbst deklarieren, anwenden und zur Laufzeit auslesen

Normalerweise werden vorhandene Annotationen auf den eigenen Code angewendet. Vorher müssen die Annotationen deklariert worden sein und nachher müssen sie ausgewertet werden. Obwohl die beiden letzteren Tätigkeiten seltener (oder nie) explizit vom Entwickler programmiert werden, werden im Folgenden alle drei Schritte kurz beschrieben, weil so am leichtesten die Funktion verstanden werden kann.

Für die Deklaration einer Annotation wird das Schlüsselwort "@interface" verwendet und die Parameter werden als parameterlose Methoden deklariert.

Das Beispiel deklariert eine "Normal Annotation", also einer Annotation mit mehreren Parametern.

Damit die Annotation nicht nur zur Build-Zeit, sondern auch später zur Laufzeit zur Verfügung steht, wird eine Meta-Annotation auf die neue Annotation angewendet, nämlich "@Retention(RetentionPolicy.RUNTIME)":

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention( RetentionPolicy.RUNTIME )
public @interface MeineNeueAnnotation
{
   int      meinIntParameter();
   String   meinStringParameter();
   String   meinDefaultParameter() default "xyz";
   String[] meinArrayParameter();
}

In der folgenden Minibeispielklasse wird die Annotation angewendet. Der Defaultparameter braucht nicht gesetzt zu werden, aber das Fehlen eines anderen Parameters würde zu einem Compilerfehler führen. Bitte beachten Sie die Syntax mit geschweiften Klammern für den Array-Parameter ("meinArrayParameter = { ..., ... }").

public class AnwendungMitAnnotation
{
   @MeineNeueAnnotation( meinIntParameter=42,
                         meinStringParameter="Blubb",
                         meinArrayParameter={"a","b","c"} )
   public void meineMethodeMitAnnotation()
   {
      //...
   }
}

Folgende Anwendung liest die übergebenen Parameter der Annotation zur Laufzeit aus (inklusive des Defaultparameters):

import java.lang.reflect.Method;

public class AnnotationZurLaufzeitVerwenden
{
   public static void main( String[] args ) throws Exception
   {
      Method[] methods = AnwendungMitAnnotation.class.getMethods();
      for( Method m : methods ) {
         if( m.isAnnotationPresent( MeineNeueAnnotation.class ) ) {
            MeineNeueAnnotation a = m.getAnnotation( MeineNeueAnnotation.class );
            System.out.println( "Methode:                 " + m.getName() );
            System.out.println( "meinIntParameter():      " + a.meinIntParameter() );
            System.out.println( "meinStringParameter():   " + a.meinStringParameter() );
            System.out.println( "meinDefaultParameter():  " + a.meinDefaultParameter() );
            System.out.println( "meinArrayParameter()[0]: " + a.meinArrayParameter()[0] );
            System.out.println( "meinArrayParameter()[1]: " + a.meinArrayParameter()[1] );
            System.out.println( "meinArrayParameter()[2]: " + a.meinArrayParameter()[2] );
         }
      }
   }
}

Im Beispiel wird Reflection verwendet. Eine Alternative wäre AOP (Aspect oriented Programming).

Speichern Sie die drei .java-Dateien und führen Sie folgende Kommandozeilenbefehle aus:

javac *.java

java AnnotationZurLaufzeitVerwenden

Das Ergebnis sieht so aus:

Methode:                 meineMethodeMitAnnotation
meinIntParameter():      42
meinStringParameter():   Blubb
meinDefaultParameter():  xyz
meinArrayParameter()[0]: a
meinArrayParameter()[1]: b
meinArrayParameter()[2]: c


Erläuterungen zu einigen ausgewählten Java-SE- und Java-EE-Annotationen

 
Package java.lang.annotation (Meta-Annotationen, also Annotationen, die nur auf Annotationen angewendet werden können (definiert durch "@Target(ANNOTATION_TYPE)"))
Annotation Erläuterung Deklaration
@Documented Steuert JavaDoc-Dokumentationen. @Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Documented
@Inherited Steuert die Vererbbarkeit der Annotation. @Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Inherited
@Retention @Retention (übersetzt "Bewahrung") steuert die Beibehaltung und Verfügbarkeit der Annotation-Informationen (--> Beispiel).
Enum RetentionPolicy
SOURCE Nach der Kompilierung stehen die Annotation-Informationen nicht mehr zur Verfügung.
CLASS Die Annotation-Informationen stehen in der .class-Datei noch zur Verfügung, aber nicht mehr zur Laufzeit (Default).
RUNTIME Die Annotation-Informationen stehen auch zur Laufzeit noch zur Verfügung.
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Retention
@Target @Target steuert welche Programmelemente annotiert werden können.
Enum ElementType
ANNOTATION_TYPE Annotation
TYPE Klasse, Interface (inklusive Annotation), Enum
CONSTRUCTOR Konstruktor
METHOD Methode
FIELD Attribut
LOCAL_VARIABLE Lokale Variable
PARAMETER Parameter
PACKAGE Package (über package-info.java)
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Target
 
Package java.lang
Annotation Erläuterung Deklaration
@Deprecated Markiert Programmelemente, die nicht mehr verwendet werden sollen. @Documented
@Retention(RUNTIME)
public @interface Deprecated
@Override Markiert Methoden, die eine Methode der Superklasse überschreiben.
Dies ist sinnvoll zur Dokumentation und damit sonst schwer zu findende Tippfehler vom Compiler gefunden werden.
@Target(METHOD)
@Retention(SOURCE)
public @interface Override
@SuppressWarnings Unterdrückt einzelne oder mehrere Warnmeldungen.
(Benötigte Annotationen können z.B. in Eclipse über 'Strg + 1' automatisch eingefügt werden.)
@Target({TYPE, FIELD, METHOD,
    PARAMETER, CONSTRUCTOR,
    LOCAL_VARIABLE})
@Retention(SOURCE)
public @interface
    SuppressWarnings
 
Package javax.annotation
@Resource Markiert eine allgemeine Ressource (z.B. SessionContext, DataSource, UserTransaction), die injiziert werden soll (--> Beispiel).
 
Package javax.annotation.security
@RolesAllowed Spezifiziert die Rollen, die Zugriff zu einer Klasse oder Methode haben.
 
Package javax.ejb
@EJB Indiziert eine Abhängigkeit zu einer Local- oder Remote-EJB (--> Beispiel).
@Local Deklariert das Business Interface einer Session Bean als Local-sichtbar.
@Remote Deklariert das Business Interface einer Session Bean als Remote-sichtbar (--> Beispiel).
@Stateful Kennzeichnet die Klasse als Stateful Session Bean.
@Stateless Kennzeichnet die Klasse als Stateless Session Bean (--> Beispiel).
@TransactionAttribute Setzt die Transaction Propagation einer Klasse oder Methode:
Enum TransactionAttributeType
MANDATORY Es muss bereits eine Transaktion aktiv sein. Sonst wird eine Exception geworfen.
NEVER Es darf keine Transaktion aktiv sein. Sonst wird eine Exception geworfen.
NOT_SUPPORTED Die Methode wird immer ohne Transaktion ausgeführt, auch wenn bereits vorher eine Transaktion gestartet wurde.
REQUIRED Falls bereits vorher eine Transaktion begonnen wurde, wird sie fortgesetzt.
Falls noch keine Transaktion aktiv ist, wird eine neue gestartet.
REQUIRES_NEW Unabhängig davon, ob bereits eine Transaktion aktiv ist, wird immer eine neue eigene Transaktion gestartet.
SUPPORTS Falls bereits eine Transaktion aktiv ist, wird sie verwendet. Ansonsten wird keine Transaktion verwendet.
@TransactionManagement Angabe der Transaktionssteuerung:
Enum TransactionManagementType
BEAN Bean-Managed Transactions (BMT)
CONTAINER Container-Managed Transactions (CMT)
 
Package javax.persistence
@Basic Daten zu einem Feld, z.B. EAGER / LAZY.
@Column Daten zu einem Feld, z.B. expliziter Spaltenname, maximale Länge, Nullable (--> Beispiel).
@DiscriminatorColumn Discriminator-Spalte, falls InheritanceType = SINGLE_TABLE oder JOINED (siehe auch Vererbung/Polymorphie).
@Entity Spezifiziert eine Klasse als Entity Bean (--> Beispiel, anderes Beispiel).
@GeneratedValue Spezifiziert einen Primary-Key-Generator (--> Beispiel, anderes Beispiel).
@Id Spezifiziert den Primary Key (--> Beispiel, anderes Beispiel).
@Inheritance Bestimmt die Abbildungsstrategie einer Klassenhierarchie auf eine Menge von Datenbanktabellen.
@Lob Large Object (BLOB oder CLOB).
@ManyToMany Definiert eine M:N-Relation.
@ManyToOne Definiert eine N:1-Relation.
@OneToMany Definiert eine 1:N-Relation.
@OneToOne Definiert eine 1:1-Relation.
@OrderBy Sortierung.
@PersistenceContext Injiziert einen EntityManager.
@PersistenceUnit Injiziert eine EntityManagerFactory (--> Beispiel).
@SequenceGenerator Parametriert den Primärschlüsselgenerator auf Sequenzbasis.
@Table Definiert den Tabellennamen für die Entity Bean (--> Beispiel).
@Transient Definiert nicht zu persistierende Felder.
@UniqueConstraint Definition einer Eindeutigkeitsbedingung für eine Spalte.
@Version Versionsspalte für Optimistic Locking.
 
Package javax.management
@MXBean Deklaration einer MXBean.
 
Package javax.jws
@WebService Deklariert eine Klasse oder ein Interface als Webservice.
@WebMethod Setzt zusätzliche Eigenschaften für Methoden, die als Webservice-Operation exportiert werden sollen.


Listen der Annotationen in Java SE und Java EE

Java SE 7

Unter den folgenden Links finden Sie zu den Java-SE-Packages jeweils unter der Überschrift "Annotation Types Summary" Annotation-Listen:

java.lang.annotation, java.lang, java.beans, javax.annotation, javax.annotation.processing, javax.jws, javax.jws.soap, javax.management, javax.xml.bind.annotation.adapters, javax.xml.bind.annotation, javax.xml.ws.

Java EE 7

Unter den folgenden Links finden Sie zu den Java-EE-Packages jeweils unter der Überschrift "Annotation Types Summary" Annotation-Listen (einige Annotationen sind sowohl in Java SE als auch in Java EE enthalten):

javax.annotation, javax.annotation.security, javax.ejb, javax.interceptor, javax.jws, javax.jws.soap, javax.persistence, javax.xml.bind.annotation.adapters, javax.xml.bind.annotation, javax.xml.ws.




Weitere Themen: andere TechDocs | Generics
© 2008 Torsten Horn, Aachen