Muitas vezes vemos coisas como "@Override", "@target" e assim por diante no código Java. Quem são esses?
Em Java, são "anotações".
A seguir, é apresentada a explicação da Enciclopédia Baidu: java.lang.annotation.retention pode instruir o compilador a tratar sua anotação personalizada ao definir o padrão de anotação. O compilador deixará as informações de anotação no arquivo de classe, mas não lidas pela máquina virtual, mas fornecerá apenas informações quando o compilador ou o programa de ferramentas for executado.
Em outras palavras, as anotações são baseadas em arquivos de classe e têm o mesmo efeito que as macros no idioma C.
Não há vestígios de anotação no arquivo de classe.
A base da anotação é a reflexão. Portanto, a anotação pode ser entendida como um conceito exclusivo do Java.
1. Meta Nota
No pacote Java.lang.annotation, quatro "primitivas" de anotação foram definidas.
1).@Target, usado para esclarecer o tipo que está sendo modificado: (métodos, campos, classes, interfaces, etc.)
2).@Retenção, descreve a existência de Annentation:
A anotação RetentionPolicy.Runtime existirá no arquivo ByteCode de classe e pode ser obtida através da reflexão em tempo de execução.
RetentionPolicy.Class A política de retenção padrão, a anotação existirá no arquivo ByteCode de classe, mas não pode ser obtido durante o tempo de execução.
A anotação retentionPolicy.Source existe apenas no código -fonte e não a contém no arquivo de bytecode da classe.
3).@Documentado, por padrão, as anotações não serão registradas no Javadoc, mas essa anotação pode ser usada para indicar que essa anotação precisa ser registrada.
4). @A meta-anulação herdada é uma anotação de tags e o @inerited explica que um determinado tipo de anotação é herdado.
Se um tipo de anotação usando a modificação @Inerited for usada para uma classe, a anotação será usada para uma subclasse da classe.
2. Anotações personalizadas
pacote com.joyfulmath.jvMexample.annNoTaion; importar java.lang.annotation.ElementType; importar java.lang.annotation.retention; importar java.lang.annotation.retionPolicy; import java.lang.annotation.target;/***authorMorMornMorm.lan.Untation.Target;/**lAthorMorMorn. 13:36*/@Target (ElementType.field) @retention (retentionpolicy.runtime) public @interface frutname {string value () padrão "";} Primeiro de tudo, uma anotação geralmente requer modificações de 2 meta -anotação:
@Target (elementType.field)
@Retention (retentionpolicy.runtime)
As funções específicas foram explicadas acima.
Todas as anotações terão uma seção semelhante a "func". Isso pode ser entendido como um parâmetro de anotação.
pacote com.joyfulmath.jvMexample.annNoTaion; import com.joyfulmath.jvmexample.tracelog;/*** @author deman.lu*@version em 2016-05-23 13: 37*/public class Apple {@fruitname ("Apple) () String; O registro deste código:
05-23 13: 39: 38.780 26792-26792/com.joyfulmath.jvMexample i/Apple: DisplayAppleName: null [at (Apple.java:16)]
Por que a tarefa não é bem -sucedida? Como atribuir o arquivo à anotação "Apple"? Como fazer isso se o compilador ainda não souber.
3. Processador de anotação
Também precisamos de um processador para explicar como as anotações funcionam, caso contrário, será quase o mesmo que as anotações.
Através da reflexão, o conteúdo da anotação pode ser obtido:
pacote com.joyfulmath.jvMexample.annNoTaion; importar com.joyfulmath.jvmexample.tracelog; importar java.lang.reflect.field;/*** @author Deman.lu*@version em 2016-05-23 14: 08*/public fruitinfoutils {public static em 2016-05-23 14: 08*/public fruitinfoutils {public stain ""; Campo [] campos = clazz.getDecLaredFields (); para (campo de campo: campos) {if (field.isannotationPresent (fruitname.class)) {fruitname fruitname = field.getAnnotation (fruitname.class); fruitStrEstr = fruitname.Value ();Este é o uso geral de anotações.
Análise da estrutura de anotação Android
Como pode ser visto no exposto, o uso de estruturas de anotação exige essencialmente a reflexão.
Mas se eu usar a estrutura de anotação com a função da reflexão, eu também poderia usá -la diretamente, é mais simples.
Se houver um mecanismo, isso pode evitar escrever muitos códigos semelhantes duplicados, especialmente durante o desenvolvimento do Android, um grande número de FindViewById & OnClick e outros eventos são correspondentes.
O padrão de código é consistente, mas o código é diferente. Neste momento, o uso da estrutura de anotação pode economizar muito tempo de desenvolvimento e, é claro, aumentará outras sobrecarga de acordo.
Aqui está um exemplo de usar o Butterknife:
@Bindstring (r.string.login_error)
String LogInerRorMessage;
Parece muito simples, é atribuir uma string ao valor inicial correspondente a String res. Dessa forma, você pode economizar algum tempo. Claro que este é apenas um exemplo.
Se você usar outras anotações, poderá economizar muito tempo de desenvolvimento.
Vamos ver como é implementado:
pacote butterknife; importar android.support.annotation.stringres; importar java.lang.annotation.retention; importar java.lang.annotation.target; importar java estático. <pre> <code>* {@literal @} bindString (r.string.username_error) string userramerRortext;* </code> </pre>*/ @retention (classe) @target (campo) public @interface bindstring {/** string recurso ID para o qual o campo será limitado. */@Stringres int value ();} O BindString possui apenas um parâmetro, valor, ou seja, atribuindo o valor a @StringRes.
O mesmo que acima, acima, é onde a anotação é definida e usada, mas a verdadeira explicação da anotação é a seguinte: ButterKnifeProcessor
mapa privado <typeElement, bindingclass> FindAndParsetArgets (Roundenvironment Env)
Esta função intercepta algum código:
// Processe cada elemento @bindstring.for (elemento elemento: Env.getElementsanNoTatedWith (bindString.class)) {if (! SuperficialValidation.valatelement (element)) continua; Try {parseResourCestring (elemento, logClassMap, eSedetNames (} Catch (Exception e) {LOGPPARPPARPPROPROPPROPROTR, ERESTING (} Catch (Exception e), e -sedSern; Encontre todos os elementos das anotações do BindString e comece a analisar:
ParseResourcestring de void privado (elemento elemento, mapa <typeElement, bindingclass> TargetClassMap, set <TypeEleement> ERASEDTARGETNAMES) {boolean hasError = false; typeElement enclokingElement = (typeelement) element.getEnclosingElement (); // verifique que o tipo de alvo é strac (! String_type.equals (element.astype (). Tostring ())) {error (elemento, "@%s tipo de campo deve ser 'string'. (%S.%S)", bindString.class.getSimplEname (), enclokingElement.getQualifiedName (), elementSimplame (); restrições.haserror | = isinAccessibleViaGeneratedCode (bindString.class, "campos", elemento); hasError | = isbindinginwrongpackage (bindString.class, elemento); if (hasError) {return;} // sinalize informações no campo.string = eleg.get.get.get.gget); element.getannotation (bindString.class) .Value (); bindingclass bindingclass = getorCreateTargetClass (TargetClassMap, EncloSingElement); CampeResourceBinding Binding = New FieldResourceBinding (ID, Name, "GetString", " false); bindingclass.addresource (ligação); ERASEDTARGETNAMES.ADD (EncloSingElement);} Primeiro, verifique se o elemento é um tipo de string.
// monta informações sobre o campo.String Nome = element.getSimpleName (). ToString (); int id = element.getAnnotation (bindString.class) .Value ();
Obtenha o nome do campo e o ID da string.
final
Mapa <typeElement, bindingclass> TargetClassMap
Elementos e descrições de anotação são armazenados um por um no mapa.
@Override Public Boolean Process (Set <? Extende TypeElement> Elements, Roundenvironment Env) {map <TypeElement, BindingClass> TargetClassMap = findAndParsetArgets (Env); para (Map.EnTRY <TypeELEMENT, BindingClass> Entrada: TargetMap.entRetSet ()) {typeELement typeelement, typeELement, typeLement, BindingClass> Entrada: TargetMap.entSet ()) {typeELement Entry.getValue (); tente {BindingClass.BrewJava (). WritEto (Filer);} Catch (IoException E) {Error (TypeElement, "Não é possível escrever Binder para Tipo %S: %S", TypeElement, E.GetMessage ()); É aqui que a estrutura de anotação é iniciada, um processo independente. Este artigo não estudará os detalhes específicos, apenas limpe -o, este é o local orientado pela estrutura.
A partir das informações acima, todas as informações de anotação são armazenadas no TargetClassMap.
O código marcado como vermelho acima deve ser o núcleo da estrutura de anotação.
Desde o Java SE5, o Java introduziu a APT Tool, que pode pré -processar anotações. O Java SE6 suporta o processador de anotação estendida.
E processar várias vezes durante a compilação. Podemos usar um processador de anotação personalizado para gerar novo código Java de acordo com as regras quando o Java for compilado .
Javafile brewjava () {typeSpec.builder resultado = typeSpec.classbuilder (generatedclassName) .addmodifiers (public); if (isfinal) {result.addmodifiers (modifier.Final);} else {result.addtypevariable (typevariAbleName.get ("t", TargetTypeName));} nome do tipo TargetType = isFinal? TargetTyPename: typevariablename.get ("t"); if (hasParentBinding ()) {result.superclass (parametReizadoTypeName.get (parentBinding.GeneratedClassName, TargetType);} else {result.addsuperInterface (parametReedTypeName.get (ViewindIndM); if (isGeneratingUnbinder ()) {result.addtype (CreateUnBinderClass (TargetType));} else if (! isFinal) {result.addmethod (CreateBindtoTargetMethod ();} Return javafile.builder (generatedClsName.packod (); da faca de manteiga. A chave para esta passagem é criar um novo arquivo.
Em seguida, escreva o conteúdo relevante.