Quais tipos podem ser usados ​​para membros da anotação Java?

238

Hoje eu queria criar minha primeira interface de anotação seguindo esta documentação e recebi esse erro do compilador

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

Obviamente, Objectnão pode ser usado como tipo de membro de anotação. Infelizmente, não consegui encontrar nenhuma informação sobre quais tipos podem ser usados ​​em geral.

Descobri isso usando tentativa e erro:

  • String → Válido
  • int → Válido
  • Integer → Inválido (Surpreendentemente)
  • String[] → Válido (Surpreendentemente)
  • Object → Inválido

Talvez alguém possa esclarecer quais tipos são realmente permitidos e por quê.

Daniel Rikowski
fonte
possivelmente varia de acordo com a anotação - mostre o código que você está tentando escrever.
djna 22/09/09
2
Adicionado à pergunta. Mas acho que não varia.
21411 Daniel Rikowski

Respostas:

324

É especificado na seção 9.6.1 do JLS . Os tipos de membros da anotação devem ser um dos seguintes:

  • primitivo
  • Corda
  • um Enum
  • outra anotação
  • Classe
  • uma matriz de qualquer um dos acima

Parece restritivo, mas sem dúvida há razões para isso.

Observe também que matrizes multidimensionais (por exemplo String[][]) são implicitamente proibidas pela regra acima.

Matrizes de classe não são permitidas, conforme descrito nesta resposta .

skaffman
fonte
33
Como alguém encontra essas páginas / documentos? Juro que pesquiso no Google todas as vezes antes de perguntar no StackOverlow e em muitas perguntas sobre Java, alguém publica um link para o JSL que responde à minha pergunta. Por que não encontro essas páginas pelo Google ?!
Daniel Rikowski
10
O JLS não é muito amigável para o Google. Você só precisa saber que está lá.
skaffman
1
as mesmas informações também estão disponíveis no guia de anotações no site da sun (que encontrou no Google): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Sim, também encontrei essa página, mas devo ter perdido essa frase, escondida em todo o texto em prosa. Procurei algo mais como tabela ou lista.
21711 Daniel Rikowski
13
O que está faltando na lista acima é "Anotação". Você pode ter uma anotação que contenha outra anotação ou uma matriz de outra anotação.
Matt
58

Eu concordo com Skaffman para os tipos disponíveis.

Restrição adicional: deve ser uma constante em tempo de compilação .

Por exemplo, é proibido o seguinte:

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

Além disso, não esqueça que as próprias anotações podem fazer parte de uma definição de anotação . Isso permite aninhamento simples de anotações - útil nos casos em que você gostaria que uma anotação estivesse presente várias vezes.

Por exemplo:

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

onde SimpleAnnotationesta

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

e ComplexAnnotationé

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

Exemplos retirados de: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

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

fikovnik
fonte
6
Com o Java 8 @Repeatable, isso não é mais necessário.
Mordechai
11

O conceito de anotações se encaixa muito bem com o design do meu projeto, até que eu percebi que você não pode ter tipos de dados complexos na anotação. Eu consegui contornar isso usando a classe do que eu queria instanciar, em vez de um objeto instanciado dessa classe. Não é perfeito, mas java raramente é.

@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
fonte