Які типи можна використовувати для членів анотацій Java?


238

Сьогодні я хотів створити свій перший інтерфейс анотацій за цією документацією, і я отримав цю помилку компілятора

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

Очевидно, Objectне можна використовувати як тип члена анотації. На жаль, я не зміг знайти жодної інформації про те, які типи можна використовувати взагалі.

Це я з’ясував, використовуючи пробні та помилки:

  • String → Дійсно
  • int → Дійсно
  • Integer → Недійсний (дивно)
  • String[] → Дійсно (дивно)
  • Object → Недійсний

Можливо, хтось може пролити трохи світла на те, які типи фактично дозволені та чому.


можливо, вона залежить від анотації - покажіть код, який ви намагаєтесь написати.
djna

2
Додано до питання. Але я не думаю, що це змінюється.
Даніель Ріковський

Відповіді:


324

Це визначено розділом 9.6.1 JLS . Типи членів анотації повинні бути одним із:

  • примітивні
  • Рядок
  • Енум
  • ще одна Анотація
  • Клас
  • масив будь-якого з перерахованих вище

Це здається обмежуючим, але, без сумніву, для цього є причини.

Також зауважте, що багатовимірні масиви (наприклад String[][]) неявно заборонені вищезазначеним правилом.

Масиви класу заборонені, як описано у цій відповіді .


33
Як можна знайти ці сторінки / документи? Я клянусь, що кожен раз переглядаю Google, перш ніж задавати StackOverlow і на багатьох питаннях Java хтось розміщує посилання на JSL, яке відповідає на моє запитання. Чому я не знаходжу ці сторінки через Google ?!
Даніель Ріковський

10
JLS не дуже зручний у користуванні Google. Вам просто потрібно знати, що він є.
skaffman

1
та ж інформація також доступна в керівництві анотацій на сайті Сонця (знайшли , що вдаючись до допомоги): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
WDS

1
Так, я знайшов і цю сторінку, але я, мабуть, пропустив це речення, приховане у всьому тому прозовому тексті. Я шукав щось більш подібне до таблиці чи списку.
Даніель Ріковський

13
Чого не вистачає у наведеному вище списку, це "Анотація". Ви можете мати примітку, яка містить іншу примітку, або масив іншої примітки.
Метт

58

Я погоджуюся зі Скафманом щодо наявних типів.

Додаткове обмеження: воно повинно бути постійною у часі компіляції .

Наприклад, заборонено:

@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())

31

Також не забувайте, що самі примітки можуть бути частиною визначення приміток . Це дозволяє зробити декілька простих приміток для внесення приміток - це зручно у тих випадках, коли ви хочете мати одне примітку багато разів.

Наприклад:

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

де SimpleAnnotationє

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

і ComplexAnnotationє

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

Приклади, взяті з: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

(оригінальна URL: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations )


6
З Java 8 @Repeatableце більше не потрібно.
Мордехай

11

Концепція анотацій дуже добре вписується в дизайн мого проекту, поки я не зрозумів, що в анотації не може бути складних типів даних. Я обійшов його, використовуючи клас того, що хотів інстанціювати, а не миттєвий об'єкт цього класу. Це не ідеально, але ява рідко є.

@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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.