Какие типы могут использоваться для членов аннотации 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 . Типы элементов аннотации должны быть одного из:

  • примитивный
  • строка
  • Enum
  • другая аннотация
  • Класс
  • массив любого из вышеперечисленного

Это кажется ограничительным, но, несомненно, есть причины для этого.

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

Массивы класса не допускаются, как описано в этом ответе .

skaffman
источник
33
Как найти эти страницы / документы? Клянусь, я гуглю каждый раз перед тем, как спрашивать о StackOverlow, и по многим вопросам Java кто-то публикует ссылку на JSL, которая отвечает на мой вопрос. Почему я не нахожу эти страницы через Google ?!
Даниэль Риковски
10
JLS не очень дружелюбен к Google. Вам просто нужно знать, что это там.
Скаффман
1
та же информация также доступна в руководстве по аннотациям на сайте Sun (он обнаружил, что поиск в Google): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Да, я тоже нашел эту страницу, но, должно быть, я пропустил это предложение, скрытое во всем этом прозаическом тексте. Я искал что-то более настольное или похожее на список.
Даниэль Риковски
13
Чего не хватает в приведенном выше списке, это «Аннотация». Вы можете иметь аннотацию, которая содержит другую аннотацию или массив другой аннотации.
Мэтт
58

Я согласен со Скаффманом для доступных типов.

Дополнительное ограничение: это должна быть константа времени компиляции .

Например, запрещено следующее:

@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())
KLE
источник
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 )

fikovnik
источник
6
С Java 8 @Repeatableэто больше не нужно.
Мордехай
11

Концепция аннотаций очень хорошо согласуется с дизайном моего проекта, пока я не понял, что в аннотации не может быть сложных типов данных. Я справился с этим, используя класс того, что я хотел создать, а не объект этого класса. Это не идеально, но редко бывает Java.

@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
}
мистифицировать
источник