Jakie typy mogą być używane dla członków adnotacji Java?

238

Dzisiaj chciałem utworzyć swój pierwszy interfejs adnotacji zgodnie z tą dokumentacją i dostałem ten błąd kompilatora

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

Oczywiście Objectnie można go użyć jako typu elementu adnotacji. Niestety nie mogłem znaleźć żadnych informacji na temat tego, które typy można ogólnie zastosować.

Przekonałem się o tym metodą prób i błędów:

  • String → Ważne
  • int → Ważne
  • Integer → Nieprawidłowy (zaskakująco)
  • String[] → Ważne (zaskakująco)
  • Object → Nieprawidłowy

Być może ktoś może rzucić nieco światła na to, które typy są dozwolone i dlaczego.

Daniel Rikowski
źródło
być może zależy to od adnotacji - pokaż kod, który próbujesz napisać.
djna
2
Dodano do pytania. Ale nie sądzę, że to się zmienia.
Daniel Rikowski

Odpowiedzi:

324

Jest to określone w sekcji 9.6.1 JLS . Typy elementów adnotacji muszą być jednym z:

  • prymitywny
  • Strunowy
  • Enum
  • kolejna adnotacja
  • Klasa
  • tablica dowolnego z powyższych

Wydaje się to restrykcyjne, ale bez wątpienia istnieją ku temu powody.

Należy również pamiętać, że tablice wielowymiarowe (np. String[][]) Są domyślnie zakazane przez powyższą zasadę.

Tablice klasy nie są dozwolone, jak opisano w tej odpowiedzi .

skaffman
źródło
33
Jak znaleźć te strony / dokumenty? Przysięgam, że google za każdym razem, zanim zadam pytanie na StackOverlow i na wiele pytań Java ktoś zamieszcza link do JSL, który odpowiada na moje pytanie. Dlaczego nie mogę znaleźć tych stron za pośrednictwem Google ?!
Daniel Rikowski
10
JLS nie jest zbyt przyjazny dla Google. Musisz tylko wiedzieć, że tam jest.
skaffman
1
te same informacje są również dostępne w przewodniku adnotacji na stronie firmy Sun (znalazłem to googling): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Tak, też znalazłem tę stronę, ale musiałem przeoczyć to zdanie, ukryte w całym tekście prozy. Szukałem czegoś bardziej podobnego do tabeli lub listy.
Daniel Rikowski
13
Na powyższej liście brakuje „Adnotacji”. Możesz mieć adnotację, która zawiera inną adnotację lub tablicę innej adnotacji.
Matt
58

Zgadzam się z Skaffmanem na dostępne typy.

Dodatkowe ograniczenie: musi to być stała czasowa kompilacji .

Na przykład zabronione są:

@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())
KLE
źródło
31

Nie zapominaj również, że same adnotacje mogą być częścią definicji adnotacji . Umożliwia to proste zagnieżdżanie adnotacji - przydatne w przypadkach, w których chciałbyś mieć jedną adnotację wiele razy.

Na przykład:

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

gdzie SimpleAnnotationjest

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

i ComplexAnnotationjest

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

Przykłady zaczerpnięte z: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

(oryginalny adres URL: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations )

fikovnik
źródło
6
W Javie 8 @Repeatablenie jest to już potrzebne.
Mordechai
11

Pojęcie adnotacji bardzo dobrze pasuje do projektu mojego projektu, dopóki nie zdałem sobie sprawy, że w adnotacji nie można mieć złożonych typów danych. Obejrzałem to, używając klasy tego, co chciałem utworzyć, a nie obiektu tej klasy. To nie jest idealne, ale java rzadko.

@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
źródło