As anotações (também conhecidas como metadadas) fornecem uma maneira formal de adicionar informações em nosso código, permitindo -nos usar esses dados de maneira muito conveniente em algum momento posterior.
1. Sintaxe básica
Java SE5 tem três anotações padrão internas
@Override: indica que a definição atual do método substituirá os métodos na superclasse. Se você soletrar acidentalmente a ortografia errada ou a assinatura do método não corresponde ao método substituído, o compilador emitirá uma mensagem de erro.
@Deprecated: Se o programador usar um elemento anotado, o compilador emitirá uma mensagem de aviso
@SupPperessWarnings: Feche a mensagem de aviso inadequada do compilador.
Java SE5 tem quatro meta anotações embutidas
@Target: indica onde essa anotação pode ser usada. Os possíveis parâmetros elementType incluem:
1) Construtor: a declaração do construtor
2) Campo: Declaração de Domínio (incluindo instâncias de Enum)
3) Local_variable: Declaração de variável local
4) Método: declaração do método
5) Pacote: Declaração do pacote
6) Parâmetro: Declaração do parâmetro
7) Tipo: classe, interface (incluindo tipo de anotação) ou declaração de enum
@Retention: indica em que nível salvar as informações de anotação. Os parâmetros de retenção opcionais incluem:
1) Fonte: A anotação será descartada pelo compilador
2) Classe: as anotações estão disponíveis em arquivos de classe, mas serão descartadas pela VM
3) Tempo de execução: a VM também manterá as anotações durante o tempo de execução, para que as informações de anotação possam ser lidas através do mecanismo de reflexão.
@Documented: Inclua esta anotação no Javadoc
@InHerited: Permita que as subclasses herdem anotações nas classes dos pais na maioria das vezes, os programadores definem principalmente suas próprias anotações e escrevem seus próprios processadores para lidar com eles.
USECASE.JAVA
pacote com; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.target; @Target (elementType.method) // Use para definir onde sua anotação será aplicada, e isso é aplicado como um método // Use para definir em que nível a anotação está disponível, no código -fonte (classe) ou tempo de execução (tempo de execução) @retention (retentionPolicy.Runtime) public @Interface USECASE {Public ID (); public string description () padrão "sem descrição"; } Senha do pacote .java com; public class PasswordUtils {@UseCase (id = 47, description = "As senhas devem conter pelo menos um numérico") public boolean validepassword () {return true; } @UseCase (id = 48) public string EncryptPassword (string senha) {return senha; } @UseCase (id = 49, description = "jong_cai") public void mostrado nome () {System.out.println ("jong_cai"); }}
2. Escreva o processador de anotação
Se não houver ferramenta para ler anotações, as anotações não serão mais úteis que as anotações. No processo de uso de anotações, uma parte importante é criar e usar processadores de anotação. O Java SE5 estende a API do mecanismo de reflexão para ajudar os programadores a construir essas ferramentas. Ao mesmo tempo, ele também fornece uma ferramenta externa apta para ajudar os programadores a analisar o código -fonte Java com anotações. Abaixo está um processador de anotação muito simples, que usaremos para ler a classe PasswordUtils e usar o mecanismo de reflexão para encontrar a tag @UseCase. Fornecemos um conjunto de valores de ID e, em seguida, ele lista os casos de uso encontrados no PasswordUtils, bem como nos casos de uso ausentes.
Pacote usecaseTracker.java com; importar java.lang.reflect.method; importar java.util.arraylist; importar java.util.Collections; importar java.util.list; classe pública usecaseTracker {public static void TrackuseCases (lista <Teger> List, classe <?> cl) {for (método m: cl.getDecLaredMethods ()) {usecase US = m.getAnnotation (usecase.class); if (nós! = null) {System.out.println ("Encontrado caso de uso:" + US.id () + "" + US.Description ()); list.Remove (novo número inteiro (US.id ())); }} para (int i: list) {System.out.println ("Aviso: falta de uso de uso-" + i); }} public static void main (string [] args) {list <Teger> list = new ArrayList <Teger> (); Coleções.addall (Lista, 47,48,49,50,51); trackuseCases (list, senhaTUtils.class); }}
Este programa usa dois métodos de reflexão: getDecLaredMethods () e GetAnnotation (). Ambos pertencem à interface AnnoTatedElement (classe, método e campo e outras classes implementam essa interface). O método getAnnotation () retorna um objeto de anotação do tipo especificado, que é a USECASE. Se o método anotado não tiver uma anotação do tipo, ele retornará um valor nulo. Em seguida, extraímos o valor do elemento do objeto de USECASE retornado chamando os métodos id () e descrição (). O método EncryptPassword () não especifica o valor da descrição ao anotar; portanto, quando o processador processa sua anotação correspondente, o valor padrão do método Descrição () é obtido pelo método Descrição ().
A anotação está se espalhando no mundo de Java. Se você tiver tempo, escreva este artigo de anotações simples. É uma introdução à anotação. Espero que você possa jogar um tijolo e aprender juntos ...
Se você parar de falar bobagem, a prática é o ponto principal.
3. Exemplo
Vamos falar primeiro sobre o conceito de anotação e depois falar sobre como projetar sua própria anotação.
Primeiro, no pacote Java.lang.annotation que vem com o JDK, abra os seguintes arquivos de origem:
Origem de arquivo de origem Target.java
@Documented @retention (retentionPolicy.Runtime) @target (elementType.annotation_type) public @Interface Target {elementType [] value (); @Documented @retention (retentionPolicy.Runtime) @target (elementType.annotation_type) public @Interface Target {elementType [] value (); }
@Interface é uma palavra -chave. Ao projetar anotações, um tipo deve ser definido como @Interface e você não pode usar as palavras -chave de classe ou interface (você acha que o Sun é um pouco mesquinho, mas parece tão semelhante à interface).
Origem do arquivo de origem retenção.java
@Documented @retention (retentionPolicy.Runtime) @target (elementType.annotation_type) public @Interface Retention {retentionPolicy value (); } @Documented @retention (retentionPolicy.Runtime) @target (elementType.annotation_type) public @Interface Retention {retentionPolicy value (); }
Depois de ver isso, você pode ser vago e não sabe do que está falando. Não se preocupe, dê uma olhada. Os arquivos acima usam os dois campos RetentionPolicy e ElementType, e você pode adivinhar que esses são dois arquivos Java. De fato, os códigos de origem desses dois arquivos são os seguintes:
File de origem RetentionPolicy.java
public Enum RetentionPolicy {origem, classe, tempo de execução} public Enum RetentionPolicy {origem, classe, tempo de execução} Este é um tipo de enumeração, com três valores, a saber, classe, classe e tempo de execução.
Fonte significa que as informações do tipo de anotação serão retidas apenas no código -fonte do programa. Se o código -fonte for compilado, os dados de anotação desaparecerão e não serão retidos no arquivo .class compilado.
Classe significa que as informações do tipo de anotação são retidas no código -fonte do programa e também serão retidas no arquivo .class compilado. Ao executar, essas informações não serão carregadas na máquina virtual (JVM). Observe que quando você não define um valor de retenção do tipo de anotação, o valor padrão do sistema é classe.
O terceiro é o tempo de execução, o que significa que as informações são retidas no código -fonte e compiladas.
Por exemplo, se a retenção no @Override estiver definida como fonte, se a compilação for bem -sucedida, você não precisará dessas informações verificadas; Pelo contrário, a retenção em @Deprecated está definida como tempo de execução, o que significa que, além de nos alertar qual método é usado durante a compilação, você também pode verificar se o método está descontinuado ao executar.
Origem de arquivo elementType.java
public enum elementType {type, campo, método, parâmetro, construtor, local_variable, anotação_type, pacote} public enum elementType {type, campo, método, parâmetro, construtor, local_variable, annotation_type, pacote} @O elementType no destino é usado para especificar quais elementos o tipo de anotação pode ser usado. Vamos explicar: tipo (tipo), campo (atributo), método (método), parâmetro (parâmetro), construtor (construtor), local_variable (variável local), anotação_type, pacote (pacote), onde o tipo (tipo) se refere a ele ser usado na interface, interface, enum e anúncio.
Além disso, pode ser visto no código -fonte de 1 que o próprio @target também se usou para se declarar e só poderia ser usado no anotação_type.
Se um tipo de anotação não especificar quais elementos @Target são usados, ele poderá ser usado em qualquer elemento e o elemento aqui se refere aos oito tipos acima.
Deixe -me dar alguns exemplos corretos:
@Target (elementType.method)
@Target (value = elementType.method)
@Target (elementType.method, elementType.Constructor)
Consulte a documentação javadoc para obter detalhes
Todos os arquivos de origem usam @Documented. O objetivo do @Documented é permitir que essas informações do tipo anotação sejam exibidas no documento de descrição Javaapi; Se não for adicionado, as informações geradas por esse tipo não serão encontradas ao usar o Javadoc para gerar o documento da API.
Outro ponto é que, se você precisar herdar dados de anotação para uma subclasse, usará o tipo de anotação @Irited.
A seguir, é o exemplo de anotação mais simples a ser projetado, que consiste em quatro arquivos;
Descrição.Java
pacote leve.javaeye.com; importar java.lang.annotation.Documented; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.target; @Target (elementType.type) @retention (retentionPolicy.Runtime) @Documented public @Interface Descrição {String value (); } pacote leve.javaeye.com; importar java.lang.annotation.Documented; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.target; @Target (elementType.type) @retention (retentionPolicy.Runtime) @Documented public @Interface Descrição {String value (); }
Nota: Todas as anotações herdarão automaticamente a interface java.lang.annotation, para que você não possa herdar outras classes ou interfaces.
O ponto mais importante é como definir os parâmetros no tipo de anotação:
Primeiro, você só pode usar os direitos de acesso público ou padrão para modificá -lo. Por exemplo, string value (); Aqui defina o método para o tipo padrão padrão.
Segundo, os membros do parâmetro podem usar apenas oito tipos de dados básicos: byte, curto, char, int, longa, flutuação, dupla, booleana e tipos de dados como string, enum, classe, anotações, bem como matrizes desses tipos. Por exemplo, string value (); O membro do parâmetro aqui é string.
Terceiro, se houver apenas um membro do parâmetro, é melhor definir o nome do parâmetro como "Value" e adicionar colchetes posteriormente. Exemplo: o exemplo acima possui apenas um membro do parâmetro.
Name.java
pacote leve.javaeye.com; importar java.lang.annotation.Documented; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.target; // Observe que o @Target aqui é diferente do @Description, e os membros do parâmetro também são diferentes @target (elementType.method) @retention (retentionPolicy.Runtime) @Documented public @Interface Name {String originate (); Comunidade de String (); } pacote leve.javaeye.com; importar java.lang.annotation.Documented; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retEntionPolicy; importar java.lang.annotation.target; // Observe que o @Target aqui é diferente do @Description, e os membros do parâmetro também são diferentes @target (elementType.method) @retention (retentionPolicy.Runtime) @Documented public @Interface Name {String originate (); Comunidade de String (); }
Javaeyer.java
pacote leve.javaeye.com; @Description ("Javaeye, seja a melhor comunidade de troca de desenvolvimento de software") Classe pública Javaeyer {@Name (Originate = "Fundador: Robbin", Community = "Javaeye") public string getName () {return null; } @Name (Originate = "Fundador: Jiangnan Baiyi", Community = "Springside") public String getName2 () {Return "pegue emprestado dois IDs de IDs, por favor me perdoe por escrever este exemplo!"; }} pacote leve.javaeye.com; @Description ("Javaeye, seja a melhor comunidade de troca de desenvolvimento de software") Classe pública Javaeyer {@Name (Originate = "Fundador: Robbin", Community = "Javaeye") public string getName () {return null; } @Name (Originate = "Fundador: Jiangnan Baiyi", Community = "Springside") public String getName2 () {Return "pegue emprestado dois IDs de IDs, por favor me perdoe por escrever este exemplo!"; }}Escreva uma aula de anulação de testes que possa executar as informações de extrato javaeyer
pacote leve.javaeye.com; importar java.lang.reflect.method; importar java.util.hashset; importar java.util.set; public class Testannotation { / *** Autor LIMPERENTE* NOTA: Para detalhes, consulte a documentação javadoc para o uso da API de anotação* / public static void main (string [] args) lança exceção {string class_name = "mais leve.javaeye.com.javaeyer"; Classe teste = classe.ForName (classe_name); Método [] método = test.getMethods (); bandeira booleana = test.isannotationPresent (description.class); if (flag) {descrição DES = (description) test.getannotation (description.class); System.out.println ("Descrição:"+des.value ()); System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- HASHSET <Método> (); System.Println (Comunidade criada: "Nome.Community ()); API de anotação*/ public static void main (string [] args) lança Exceção {string class_name = "mais leve.javaeye.com.javaeyer"; Classe teste = classe.ForName (classe_name); Método [] método = test.getMethods (); bandeira booleana = test.isannotationPresent (description.class); if (flag) {descrição DES = (description) test.getannotation (description.class); System.out.println ("Descrição:"+des.value ()); System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { Boolean Otherflag = Método [i]. Resultados em execução:
Descrição: Javaeye, o melhor fundador da comunidade de troca de desenvolvimento de software: Robbin Criado Comunidade: Javaeye Fundador: Javaeye Comunidade criada: Springside