Eine Reihe von Annotationstypen sind standardmäßig vordefiniert und für
jeden dieser Typen existiert eine Klassendatei. So ist z.B. die zum vordefinierten
Annotationstyp Programmelemente wie z.B. Methoden können mit java.lang Annotation Type Deprecated 1.5 @Documented @Retention(value=RUNTIME) public @interface Deprecated Die folgende Klasse besitzt die Mehtode /* A_Deprecated.java */ public class A_Deprecated { /** * @deprecated Die Methode methode_A wurde seit Version 1.5 als * deprecated eigestuft. */ @Deprecated public static void methode_A () { System.out.println("Diese Methode wurde als deprecated eingestuft."); } } Der Methodendeklaration wurde auch ein Javadoc-Kommentar (beginnt mit den
Schlüsselzeichen "/**") vorangestellt, wobei das Schlüsselwort Abbildung 2.2. API-Dokumentation Mit Hilfe der folgenden Testklasse soll die mit /* TestDeprecated.java */ public class TestDeprecated { public static void main(String[] args) { A_Deprecated.methode_A(); } } Wird nun Note: TestDeprecated.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. Durch die Compilierung mit der Option > javac -Xlint:deprecation TestDeprecated.java führt zur Ausgabe von: TestDeprecated.java:4: warning: [deprecation] methode_A() in A_Deprecated has been deprecated A_Deprecated.methode_A(); ^ 1 warning Wenn eine Klasse eine andere erweitert, werden auch die Methoden der
Superklasse automatisch übernommen. Es besteht aber auch die Möglichkeit, eine
geerbte Methode neu zu definieren. Die geerbte Methode wird überschrieben
(überlagert). Um eine Fehlermeldung zu erhalten, falls eine Methode in einer
abgeleiteten Klasse nicht die entsprechende Methode ihrer Superklasse überschreibt
(Stichwort: Signatur vom Methoden), ist die Annotation java.lang Annotation Type Override 1.5 @Target(value=METHOD) @Retention(value=SOURCE) public @interface Override Der Einsatz von /* A_Override.java */ public class A_Override { public static void methode_A() { System.out.println("Diese Methode soll ueberlagert werden."); } } Aus der Klasse /* B_Override.java */ public class B_Override extends A_Override { @Override public static void methode_a() { System.out.println("Diese Methode soll methode_A aus der " + "Klasse A_Override ueberlagern."); } public static void main(String[] args) { B_Override.methode_A(); } } Die Compilierung von > javac B_Override.java B_Override.java:3: method does not override a method from its superclass @Override ^ 1 error Der Java-Compiler gibt z.B. eine Warnmeldung aus, wenn eine als "deprecated"
eingestufte Methode verwendet wurde, oder wenn die java.lang Annotation Type SuppressWarnings 1.5 @Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) @Retention(value=SOURCE) public @interface SuppressWarnings Element: String[] value Die Verwendung dieser Annotation veranlasst den Compiler bestimmte Warnmeldungen
zu unterdrücken. Jede Warnmeldung sollte überprüft werden und falls die Meldung
aus bestimmten Gründen nicht weiter relevant ist kann sie durch diese Annotation
unterdrückt werden. Das nächste Beispiel unterdrückt eine "unchecked"-Warnung,
die dadurch entsteht, dass der Aufruf von /* A_SuppressWarnings.java */ import java.util.*; public class A_SuppressWarnings { @SuppressWarnings("unchecked") public static void main(String[] args) { Vector v = new Vector(); v.add(new Integer(3)); Integer i = (Integer)v.iterator().next(); } } Um die Generierung einer Warnmeldung zu vermeiden (könnte und müsste dann auch nicht unterdrückt werden), könnten die folgenden Programmzeilen verwendet werden, die auf Generics zurückgreifen: Vector<Integer> v = new Vector<Integer>(); v.add(new Integer(3)); Integer i = v.iterator().next();
@SuppressWarnings(value = {"unchecked"}) @SuppressWarnings({"unchecked"}) @SuppressWarnings("unchecked") Bei der Deklaration von Versionen (JDK 5): Die
Annotation Annotationen zu Klassen oder Methoden erscheinen standarmäßig nicht in der
API-Dokumentation (Javadoc) der verwendenden Klasse. Soll eine Annotation dennoch
mit in die Javadocs aufgenommen werden, kann dies dadurch ermöglicht werden,
dass bei der Deklaration ihres Typs java.lang.annotation Annotation Type Documented 1.5 @Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Documented Bei der Definition des eigenen Annotationstyps @Documented ... public @interface Autor { ... } Wird nun eine derart deklarierter Annotationstyp innerhalb eine Listings
verwendet und anschließend von diesem Listing mittels public class AnnotationExample { @Autor(id = 1, name = "im Glueck", vorname = "Hans") public static void methodeVonHansImGlueck() { ... } ... } würde dann wie folgt erzeugt werden (in der Dokumentation wird die Annotation
Abbildung 2.3. API-Dokumentation (Ausschnitt) von Eine neue Klasse die eine bestehende Klasse erweitert erbt u.a. automatisch
die Methoden der bestehenden Klasse. Annotationen, die in einer bestehenden Klasse
verwendet wurden, werden hingegen nicht automatisch in eine neue Unterklasse
vererbt. Damit aber eine Annotation bei der Ableitung einer Klasse vererbt wird,
kann bei der Deklaration ihres Annotationstyps die Meta-Annotation
java.lang.annotation Annotation Type Inherited 1.5 @Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Inherited Eine kurze Beispielbetrachtung soll die Vererbung von Annotationen erläutern.
Zunächst wird die neue Annotation /* TestClass.java */ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited public @interface TestClass { } Die folgende Klasse, die später abgeleitet werden soll, wird durch die neu erstellte Annotation markiert: /* A_Inherited.java */ @TestClass public class A_Inherited { public void ausgabe() { System.out.print("Klasse A_Inherited: "); } }
/* B_Inherited.java */ public class B_Inherited extends A_Inherited { public void ausgabe() { System.out.print("Klasse B_Inherited: "); } } Die abgeleitete Klasse /* TestInherited.java */ public class TestInherited { public static void main(String[] args) { A_Inherited ai = new A_Inherited(); B_Inherited bi = new B_Inherited(); ai.ausgabe(); if (ai.getClass().isAnnotationPresent(TestClass.class)) { System.out.println("@TestClass in Klasse A_Inherited verfuegbar!"); } bi.ausgabe(); if (bi.getClass().isAnnotationPresent(TestClass.class)) { System.out.println("@TestClass in Klasse B_Inherited verfuegbar!"); } } } Die Ausgabe des vorhergenden Testprogramms zeigt, dass die Annotation
Klasse A_Inherited: @TestClass in Klasse A_Inherited verfuegbar! Klasse B_Inherited: @TestClass in Klasse B_Inherited verfuegbar! Die Meta-Annotation java.lang.annotation Annotation Type Target 1.5 @Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Target Element: ElementType[] value Die Annotation java.lang.annotation Enum ElementType 1.5 Enum Constant: ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE Die Bezeichnungen der Konstanten deuten auf die Programmelemente hin, für
die die benutzerdefinierte Annotation gelten soll. Die Konstante
@Target(ElementType.METHOD) public @interface Autor { ... } Eine Verwendung von @Autor(id = 1, name = "im Glueck", vorname = "Hans") // Fehler public class AnnotationExample { ... } würde bei der Compilierung zu einer Fehlermeldung führen: AnnotationExample.java:9: annotation type not applicable to this kind of declaration @Autor(id = 1, name = "im Glueck", vorname = "Hans") ^ 1 error Mit der Meta-Annotation java.lang.annotation Annotation Type Retention 1.5 @Documented @Retention(value=RUNTIME) @Target(value=ANNOTATION_TYPE) public @interface Retention Element: RetentionPolicy value Die Meta-Annotation akzeptiert einen einzigen Paramter vom Typ
java.lang.annotation Enum RetentionPolicy 1.5 Enum Constant: CLASS RUNTIME SOURCE Die drei unterschiedlichen Konstanten sind dabei entsprechend maßgebend, ob eine benutzerdefinierte Annotation, in den durch die Compilierung erzeugten Bytecode (Klassendatei) des verwendenden Programms, aufgenommen wird:
Bei der Deklaration des Annotationstyps @Retention(RetentionPolicy.RUNTIME) ... public @interface Autor { ... } Diese Annotation wurde anschließend in Listing 2.3 verwendet, um eine Methode zu kennzeichnen (Ausschnitt): public class AnnotationExample { @Autor(id = 1, name = "im Glueck", vorname = "Hans") public static void methodeVonHansImGlueck() { ... } ... } Die Auswirkungen der Konstanten ca fe ba be 00 00 00 31 00 63 0a 00 1b 00 32 09 .......1.c....2. 0 ... 65 01 00 16 6d 65 74 68 6f 64 65 56 6f 6e 48 61 e...methodeVonHa 160 6e 73 49 6d 47 6c 75 65 63 6b 01 00 19 52 75 6e nsImGlueck...Run 176 74 69 6d 65 56 69 73 69 62 6c 65 41 6e 6e 6f 74 timeVisibleAnnot 192 61 74 69 6f 6e 73 01 00 07 4c 41 75 74 6f 72 3b ations...LAutor; 208 01 00 02 69 64 03 00 00 00 01 01 00 04 6e 61 6d ...id........nam 224 65 01 00 09 69 6d 20 47 6c 75 65 63 6b 01 00 07 e...im Glueck... 240 76 6f 72 6e 61 6d 65 01 00 04 48 61 6e 73 01 00 vorname...Hans.. 256 ... Die Repräsentation der Zeichenfolge |
|