Wir sehen oft Dinge wie "@Override", "@Target" und so weiter in Java -Code. Was ist das?
In Java sind sie "Anmerkungen".
Das Folgende ist die Erklärung von Baidu Encyclopedia: java.lang.annotation.Retention kann den Compiler anweisen, Ihre benutzerdefinierte Annotation zu behandeln, wenn Sie das Annotationsmuster definieren. Der Compiler hinterlässt Annotationsinformationen im Klassenarchiv, aber nicht von der virtuellen Maschine gelesen, liefert jedoch nur Informationen, wenn das Compiler- oder Tool -Programm ausgeführt wird.
Mit anderen Worten, Anmerkungen basieren auf Klassendateien und haben den gleichen Effekt wie Makros in der C -Sprache.
In der Klassendatei gibt es keine Annotation.
Die Basis der Annotation ist die Reflexion. Daher kann die Annotation als ein für Java einzigartiges Konzept verstanden werden.
1. Meta Note
Im java.lang.Annotationspaket wurden vier "Primitiven" der Annotation definiert.
1).@Ziel, verwendet, um den geänderten Typ zu klären: (Methoden, Felder, Klassen, Schnittstellen usw.)
2).@Retention beschreibt die Existenz der Annentation:
Die RetentionPolicy.
RetentionPolicy.Class Die Standard -Aufbewahrungsrichtlinie wird die Annotation in der Klassen -Bytecode -Datei vorhanden, sie kann jedoch während der Laufzeit nicht erhalten werden.
Die Annotation der RetentionPolicy.Source ist nur im Quellcode vorhanden und enthält sie nicht in der Klassen -Bytecode -Datei.
3).@Dokumentiert standardmäßig werden Anmerkungen in Javadoc nicht aufgezeichnet, aber diese Annotation kann verwendet werden, um anzuzeigen, dass diese Annotation aufgezeichnet werden muss.
4). @Erbte Meta-Annotation ist eine Tag-Annotation, und @Inherited erklärt, dass ein bestimmter kommentierter Typ vererbt wird.
Wenn für eine Klasse ein Annotationstyp mit @Inherited Modification verwendet wird, wird die Annotation für eine Unterklasse der Klasse verwendet.
2. benutzerdefinierte Anmerkungen
Paket com.joyfulmath.jvmexample.annnotaion; import Java.lang.Annotation.elementtype; Import Java.lang.Annotation.Retention; 13:36*/@target (elementtype.field) @retention (retentionPolicy.runtime) public @Interface fruitname {String value () default "";} Erstens erfordert eine Annotation im Allgemeinen 2 Meta -Annotationsänderungen:
@Target (elementtype.field)
@Retention (RetentionPolicy.Runtime)
Die spezifischen Funktionen wurden oben erklärt.
Alle Anmerkungen haben einen ähnlichen Abschnitt wie "Func". Dies kann als Annotationsparameter verstanden werden.
Paket com.joyfulmath.jvmexample.annnotaion; import com.joyfulmath.jvmexample.tracelog;/*** @Author Deman.lu*@Version am 2016-05-23 13: 37*/public class Apple Apfel
Das Protokoll dieses Code:
05-23 13: 39: 38.780 26792-26792/com.joyfullmath.jvMexample I/Apple: DisplayApplename: NULL [at (Apple.java:16)]
Warum ist die Aufgabe nicht erfolgreich? Wie habe ich die Datei der Anmerkung "Apple" zugewiesen? Wie es geht, wenn der Compiler noch nicht weiß.
3. Annotationsprozessor
Wir brauchen auch einen Prozessor, um zu erklären, wie die Anmerkungen funktionieren, sonst ist es fast dasselbe wie die Anmerkungen.
Durch Reflexion kann der Annotationsinhalt erhalten werden:
Paket com.joyfulmath.jvmexample.annnotaion; import com.joyfulmath.jvmexample.tracelog; Import Java.lang.Reflect.field;/*** @Author Deman.lu*@Version am 2016-05-23 14: 08*/public fruitinfoutils {öffentliches statisches statisches void void voiid voiid voiid Get-Get-Get-Get-Get-Get-Get-Get-Void-Void-Get-Get-Void-Void-{Class-Class <-Class-Classs {öffentliches statisches voiid voiid = ""; Field [] fields = clazz.getDeclaredfields (); für (Field Field: Fields) {if (isannotationPresent (fruitname.class)) {fruitname fruitname = field.getannotation (fruitname.class);Dies ist die allgemeine Verwendung von Anmerkungen.
Analyse von Android Annotation Framework
Wie aus den oben genannten Erscheinen hervorgeht, erfordert die Verwendung von Annotationsrahmen im Wesentlichen Reflexion.
Aber wenn ich das Annotations -Framework mit der Funktion der Reflexion verwende, kann ich es auch direkt verwenden, es ist einfacher.
Bei einem Mechanismus kann es vermeiden, viel doppelte Code zu schreiben, insbesondere während der Android -Entwicklung, eine große Anzahl von FindViewById & Onclick und anderen Ereignissen entsprechen.
Das Codemuster ist konsistent, der Code ist jedoch unterschiedlich. Zu diesem Zeitpunkt kann die Verwendung des Annotationsrahmens viel Entwicklungszeit sparen und natürlich den anderen Aufwand entsprechend erhöhen.
Hier ist ein Beispiel für die Verwendung von Butterknife:
@Bindstring (R.String.login_error)
String loginerRorMessage;
Es scheint sehr einfach zu sein, es soll dem anfänglichen Wert eine Zeichenfolge zuweisen, die der Zeichenfolge entspricht. Auf diese Weise können Sie einige Zeit sparen. Natürlich ist dies nur ein Beispiel.
Wenn Sie andere Anmerkungen stark verwenden, können Sie viel Entwicklungszeit sparen.
Mal sehen, wie es implementiert wird:
Paket Butterknife; importieren android.support.annotation.stringres; import Java.lang.Annotation <pre> <code>* {@litereral @} bindstring (r.string.username_error) String usernameErrortext; */@Stringres int value ();} BindString hat nur einen Parameter, den Wert, das heißt, den Wert @Stringres zugewiesen.
Gleich wie oben ist das obige, wo die Annotation definiert und verwendet wird, aber die wirkliche Erklärung der Annotation lautet wie folgt: ButterknifeProzessor
Private Karte <Typelement, BindingClass> findAndarsetargets (Rundumgebietsumb)
Diese Funktion fängt einen Code ab:
// jedes @BindString -Element verarbeiten.FOR (Elementelement: Env.GetElementsAnnotated with (bindstring.class)) {if (! OberficialValidation.ValidateElement (Element) Fortsetzung; try {parseresourcestring (Element, targetClassmap, lorasedTargetNames); e);}} Finden Sie alle Elemente von Bindstring -Anmerkungen und beginnen Sie mit der Analyse:
private void parseresourcestring (Elementelement, Karte <typeelement, bindingClass> targetClassmap, set <TypeLement> ERasedTargetNames) {boolean haserror = false; typeLement EnglosingElement = (TypeLement) Element.getenclosenelement (); //, dass der Zieltyp der Zieltyp ist. . Restriktionen.HasError | = isinAccessibleViageneratedCode (Bindstring.Class, "Fields", Element); Element.Getannotation (Bindstring.Class) .Value (); BindingClass BindingClass = getorCreateTargetClass (TargetClassmap, Entenschließung); FieldResourcebinding Binding = new fieldResourcebinding (id, name, "getString", Falsch); BindingClass.AdDresource (Bindung); ERASSADTARGETNAMES.ADD (EnglosingElement);} Überprüfen Sie zunächst, ob das Element ein String -Typ ist.
// Informationen über das Feld zusammenstellen.
Holen Sie sich den Namen des Feldes und die String -ID.
Finale
Karte <typelement, bindingClass> targetClassmap
Elemente und Annotationsbeschreibungen werden einzeln in der Karte gespeichert.
@Override public boolean Process (set <? Erweitert Typelement> Elemente, Rundumwelt -Env) {MAP <Typelement, BindingClass> targetClassmap = findAndarSetArgets (env); für (map.Entry <typeelement, BindingClass> Eintrag: TargetClassMap.EntrySet () {) typeLement = typelement = typeLement = typeLement = typeLement = typeLement = typeelement = typeelement = typeelement = typeelement = typeelement Entry.getValue (); try {bindingClass.brewjava (). writeTo (filer);} catch (ioException e) {error (TypElement, "nicht in der Lage, Ansicht für Typ %s: %s", typeLement, e.getMessage () zu schreiben;}} return true;} true;} true;} true;} true;} true; Hier wird das Annotationsrahmen gestartet, ein unabhängiger Prozess. In diesem Artikel werden die spezifischen Details nicht untersucht, sondern nur klar, dies ist der rahmengesteuerte Ort.
Aus den oben genannten Informationen werden alle Annotationsinformationen in der Zielklasse gespeichert.
Der oben rot gekennzeichnete Code sollte der Kern des Annotations -Frameworks sein.
Seit Java SE5 hat Java ein APT -Tool eingeführt, das Annotationen vorab. Java SE6 unterstützt den erweiterten Annotationsprozessor.
Und verarbeiten Sie es während der Zusammenstellung mehrmals. Wir können einen benutzerdefinierten Annotationsprozessor verwenden, um den neuen Java -Code gemäß den Regeln zu generieren, wenn Java zusammengestellt wird .
Javafile brewjava () {typespec.builder result = typespec.classBuilder (generiertClassName) .AddModifiers (öffentlich); if (isFinal) {result.addModifiers (modifier.final);} else {result.addtypevariable (typariableName.get ("T", TargetTypename));} Typename targetType = isfinal? TARGETTYTYPENAME: typariableName.get ("t"); if (HaSparentBinding ()) {result.superClass (parameterizedtypename.get (parentBinding.generatedClassName, TargetType));} else {result.addsuperInterface (parameterizedTypePename.get (view_binder, targetType); if (isGeneratingUnbinder ()) {result.addType (createUnbinderClass (TargetType));} else if (! isFinal) {result.addMethod (CreateBindTotargetMethod ());} return javafile.builder (generatedClasName.packaName (). Buttermesser. Der Schlüssel zu dieser Passage liegt darin, eine neue Datei zu erstellen.
Schreiben Sie dann den entsprechenden Inhalt.