Annotation (Java)

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

In Java kann mit einer Annotation Metainformation in den Quellcode eines Programmes eingefügt werden.

Annotation können von unterschiedlichsten Tools ausgelesen werden. So kann bereits ein Compiler einige Annotationen verwenden, z.B. um Warnungen zu unterdrücken oder zu generieren.

Eigene Annotationen

Es ist möglich, eigene Annotationen zu schreiben. Der Syntax einer Annotation gleicht dem Syntax eines Interfaces. Wie ein Interface muss auch eine Annotation in einer eigenen Java-Datei gespeichert werden.

Annotation definieren

Verglichen mit einem Interface hat eine Annotation folgende Unterschiede:

Ein Beispiel:

1 @Retention( RetentionPolicy.RUNTIME )
2 @Target( ElementType.METHOD )
3 public @interface IntegerSetter {
4     int min();
5     int max();
6     int start() default 1;
7 }

Die hier definierte Annotation IntegerSetter besitzt drei Elemente: "min", "max" und "start". Alle drei sind vom Typ "int". Das Element "start" besitzt einen Default-Wert von 1.

Retention und Target sind andere Annotationen, welche eine Aussage über den Gültigkeitsbereich der Annotation IntegerSetter machen. Hier wird gesagt, dass die Annotation IntegerSetter zur Laufzeit sichtbar ist, und nur für Methoden verwenden werden kann.

Annotation anwenden

Annotationen werden vor das zu markierende Element geschrieben, einfach indem nach einem @ der Name der Annotation ausgeschrieben wird. Falls die Annotation Elemente besitzt, müssen die Elemente noch gesetzt werden. Dazu schreibt man, in runden Klammern, "Element = Wert"-Paare.

Beispiel:

public class Point {
    private int x, y;
    
    @IntegerSetter( min=0, max=5 )
    public void setX( int x ){
        this.x = x;
    }
    
    @IntegerSetter( min=0, max=20, start=5 )
    public void setY( int y ){
        this.y = y;
    }
    
    public static void main( String[] args ) throws Exception{
        list( Point.class );
    }
}

Hier werden die beiden Methoden "setX" und "setY" mit IntegerSetter markiert. Da das Element "start" einen Default-Wert besitzt, ist es nicht notwendig, das Element jedesmal neu zu definieren.

Annotation zur Laufzeit auslesen

Selbstgeschriebene Annotation werden oft zur Laufzeit benötigt. Mit Reflection können die Annotation ausgelesen werden. Die meisten Reflection-Klassen bieten eine entsprechende Methode "getAnnotation(s)"

Beispiel:

 1     public static void main( String[] args ) throws Exception{
 2         list( Point.class );
 3     }
 4     
 5     public static void list( Class<?> clazz ) throws Exception{
 6         for( Method method : clazz.getMethods() ){
 7             IntegerSetter value = method.getAnnotation(
 8                 IntegerSetter.class );
 9             if( value != null ){
10                 System.out.printf( 
11                         "%s: min=%d, max=%d, start=%d\n",
12                         method.getName(), value.min(),
13                         value.max(), value.start() );
14             }
15         }
16     }

Die Ausgabe dieses Programmes ist:

setX: min=0, max=5, start=1
setY: min=0, max=20, start=5

Wie man an dem Beispiel sieht, können Annotationen wie normale Objekte behandelt werden.

Vordefinierte Annotationen

Es gibt bereits einige vordefinierte Annotationen, dieser Abschnitt präsentiert eine Auswahl aus verschiedenen Packages.

java.lang

Name Zweck
@Deprecated Markiert Elemente (Klassen, Methoden, ...), die veraltet sind, oder aus anderen Gründen nicht benutzt werden sollten. Siehe auch Deprecated.
@SuppressWarnings Veranlasst den Compiler einen oder mehrere Typen Warnungen nicht zu melden.
@Override Markiert eine Methode, die eine andere Methode überschreibt. Ein Compiler kann dank dieser Annotation sicher sein, dass der Programmierer eine Methode absichtlich überschrieben hat.

java.lang.annotation

Name Zweck
@Retention Regelt die Sichtbarkeit einer Annotation. Dazu wird eine RetentionPolicy gesetzt.
  • Source: Die Annotation ist nur im Quellcode sichtbar.
  • Class: Die Annotation ist auch in der Class-Datei, also im Kompilat, vorhanden.
  • Runtime: Die Annotation wird während der Laufzeit von der JVM geladen. Nur mit dieser Policy kann eine Annotation per Reflection ausgelesen werden.
@Target Wird ebenfalls für Annotationen angewandt. Das @Target sagt dem Compiler, welche Elemente eine Annotation markieren darf. @Target erwartet ein Array von ElementType.

Beispiel: Eine Annotation die für Methoden und Typen verwendet werden kann:

1 @Target( {ElementType.TYPE, ElementType.METHOD} )
2 public @interface Something{
3  ...
4 }
@Documented Wird für Annotationen verwendet, die von Javadoc, und ähnlichen Programmen, dokumentiert werden sollen. Das ist insbesondere wünschenswert für Annotationen, deren Vorhandensein einen direkten Einfluss auf das Programm haben.
@Inherited Markiert eine Annotation, welche vererbt werden soll. Damit ist gemeint: wenn die Annotation eine Klasse markiert, sind automatisch alle Unterklassen ebenfalls markiert.