Quels types peuvent être utilisés pour les membres d'annotation Java?

238

Aujourd'hui, je voulais créer ma première interface d'annotation en suivant cette documentation et j'ai eu cette erreur de compilation

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

De toute évidence, Objectne peut pas être utilisé comme type de membre d'annotation. Malheureusement, je n'ai trouvé aucune information sur les types pouvant être utilisés en général.

J'ai découvert cela en utilisant des essais et erreurs:

  • String → Valide
  • int → Valide
  • Integer → Invalide (Étonnamment)
  • String[] → Valide (Étonnamment)
  • Object → invalide

Peut-être que quelqu'un peut faire la lumière sur les types autorisés et pourquoi.

Daniel Rikowski
la source
cela peut varier selon l'annotation - veuillez montrer le code que vous essayez d'écrire.
djna
2
Ajouté à la question. Mais je ne pense pas que cela varie.
Daniel Rikowski

Réponses:

324

Il est spécifié par la section 9.6.1 du JLS . Les types de membres d'annotation doivent être l'un des suivants:

  • primitif
  • Chaîne
  • un Enum
  • une autre annotation
  • Classe
  • un tableau de l'un des éléments ci-dessus

Cela semble restrictif, mais il y a sans aucun doute des raisons à cela.

Notez également que les tableaux multidimensionnels (par exemple String[][]) sont implicitement interdits par la règle ci-dessus.

Les tableaux de classe ne sont pas autorisés comme décrit dans cette réponse .

skaffman
la source
33
Comment trouve-t-on ces pages / documents? Je jure que je google à chaque fois avant de poser des questions sur StackOverlow et sur de nombreuses questions Java, quelqu'un poste un lien vers le JSL qui répond à ma question. Pourquoi je ne trouve pas ces pages via Google?!
Daniel Rikowski
10
Le JLS n'est pas très convivial pour Google. Vous avez juste besoin de savoir que c'est là.
skaffman le
1
les mêmes informations sont également disponibles dans le guide d'annotation sur le site du soleil (a effectivement conclu que googler): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Oui, j'ai trouvé cette page aussi, mais j'ai dû manquer cette phrase, cachée dans tout ce texte en prose. J'ai cherché quelque chose de plus semblable à une table ou à une liste.
Daniel Rikowski
13
Ce qui manque dans la liste ci-dessus est "Annotation". Vous pouvez avoir une annotation qui contient une autre annotation ou un tableau d'une autre annotation.
Matt
58

Je suis d'accord avec Skaffman pour les types disponibles.

Restriction supplémentaire: il doit s'agir d'une constante de temps de compilation .

Par exemple, les éléments suivants sont interdits:

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

N'oubliez pas non plus que les annotations elles-mêmes peuvent faire partie d'une définition d'annotation . Cela permet une imbrication d'annotation simple - pratique dans les cas où vous souhaitez avoir une annotation présente plusieurs fois.

Par exemple:

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

SimpleAnnotationest

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

et ComplexAnnotationest

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

Exemples tirés de: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

(URL d'origine: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations )

fikovnik
la source
6
Avec Java 8 @Repeatable, cela n'est plus nécessaire.
Mordechai
11

Le concept d'annotations correspond très bien à la conception de mon projet, jusqu'à ce que je réalise que vous ne pouvez pas avoir de types de données complexes dans l'annotation. Je l'ai contourné en utilisant la classe de ce que je voulais instancier plutôt qu'un objet instancié de cette classe. Ce n'est pas parfait, mais Java l'est rarement.

@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
la source