Welche Typen können für Java-Anmerkungsmitglieder verwendet werden?

238

Heute wollte ich nach dieser Dokumentation meine erste Anmerkungsschnittstelle erstellen und habe diesen Compilerfehler erhalten

Invalid type for annotation member":
public @interface MyAnnotation {
    Object myParameter;
    ^^^^^^
}

ObjectKann offensichtlich nicht als Typ eines Anmerkungselements verwendet werden. Leider konnte ich keine Informationen darüber finden, welche Typen generell verwendet werden können.

Dies habe ich mithilfe von Versuch und Irrtum herausgefunden:

  • String → Gültig
  • int → Gültig
  • Integer → ungültig (überraschend)
  • String[] → Gültig (überraschend)
  • Object → Ungültig

Vielleicht kann jemand etwas Licht ins Dunkel bringen, welche Typen tatsächlich erlaubt sind und warum.

Daniel Rikowski
quelle
Möglicherweise variiert dies je nach Anmerkung. Bitte zeigen Sie den Code an, den Sie schreiben möchten.
DJNA
2
Zur Frage hinzugefügt. Aber ich denke nicht, dass es variiert.
Daniel Rikowski

Antworten:

324

Es ist in Abschnitt 9.6.1 des JLS angegeben . Die Anmerkungselementtypen müssen einer der folgenden sein:

  • Primitive
  • String
  • eine Aufzählung
  • eine weitere Anmerkung
  • Klasse
  • ein Array von einem der oben genannten

Es scheint restriktiv zu sein, aber es gibt zweifellos Gründe dafür.

Beachten Sie auch, dass mehrdimensionale Arrays (z. B. String[][]) durch die obige Regel implizit verboten sind.

Arrays of Class sind nicht zulässig, wie in dieser Antwort beschrieben .

Skaffman
quelle
33
Wie findet man diese Seiten / Dokumente? Ich schwöre, ich google jedes Mal, bevor ich auf StackOverlow und auf vielen Java-Fragen frage, dass jemand einen Link zur JSL veröffentlicht, der meine Frage beantwortet. Warum finde ich diese Seiten nicht über Google?!
Daniel Rikowski
10
Das JLS ist nicht sehr google-freundlich. Sie müssen nur wissen, dass es da ist.
Skaffman
1
Die gleichen Informationen finden Sie auch im Annotation Guide auf der Sun-Website (habe das Googeln gefunden): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Ja, ich habe diese Seite auch gefunden, aber ich muss diesen Satz verpasst haben, der in all dem Prosatext versteckt ist. Ich habe nach etwas mehr Tabelle oder Liste gesucht.
Daniel Rikowski
13
Was in der obigen Liste fehlt, ist "Anmerkung". Sie können eine Anmerkung haben, die eine andere Anmerkung oder ein Array einer anderen Anmerkung enthält.
Matt
58

Ich stimme Skaffman für die verfügbaren Typen zu.

Zusätzliche Einschränkung: Es muss eine Konstante für die Kompilierungszeit sein .

Zum Beispiel sind folgende verboten:

@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())
KLE
quelle
31

Vergessen Sie auch nicht, dass Anmerkungen selbst Teil einer Anmerkungsdefinition sein können . Dies ermöglicht eine einfache Verschachtelung von Anmerkungen - praktisch in Fällen, in denen eine Anmerkung mehrmals vorhanden sein soll.

Beispielsweise:

@ComplexAnnotation({
    @SimpleAnnotation(a="...", b=3),
    @SimpleAnnotation(a="...", b=3),
    @SimpleAnnotation(a="...", b=3)
})
public Object foo() {...}

wo SimpleAnnotationist

@Target(ElementType.METHOD)
public @interface SimpleAnnotation {
    public String a();
    public int b();
)

und ComplexAnnotationist

@Target(ElementType.METHOD)
public @interface ComplexAnnotation {
    public SimpleAnnotation[] value() default {};
)

Beispiele aus: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

(ursprüngliche URL: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations )

fikovnik
quelle
6
Mit Java 8 @Repeatablewird dies nicht mehr benötigt.
Mordechai
11

Das Konzept der Anmerkungen passt sehr gut zum Design meines Projekts, bis mir klar wurde, dass die Anmerkung keine komplexen Datentypen enthalten kann. Ich habe es umgangen, indem ich die Klasse von dem verwendet habe, was ich instanziieren wollte, anstatt ein instanziiertes Objekt dieser Klasse. Es ist nicht perfekt, aber Java ist es selten.

@interface Decorated { Class<? extends PropertyDecorator> decorator() }

interface PropertyDecorator { String decorate(String value) }

class TitleCaseDecorator implements PropertyDecorator {
    String decorate(String value)
}

class Person {
    @Decorated(decorator = TitleCaseDecorator.class)
    String name
}
Josh
quelle