Мы часто видим такие вещи, как «@Override», «@Target» и так далее в коде Java. Что это?
В Java они «аннотации».
Ниже приводится объяснение энциклопедии Baidu: java.lang.annotation.retention может дать инструкциям компилятора обработать пользовательскую аннотацию при определении схемы аннотации. Компилятор оставит информацию о аннотации в архиве класса, но не прочитал виртуальной машиной, а предоставит информацию только при запуске компилятора или инструментальной программы.
Другими словами, аннотации основаны на файлах класса и имеют такой же эффект, что и макросы на языке C.
В файле класса нет следов аннотации.
Основой аннотации является отражение. Следовательно, аннотацию можно понимать как концепция, уникальная для Java.
1. Мета
В пакете java.lang.annotation были определены четыре «примитивы» аннотации.
1).@Target, используется для прояснения типа, изменяемого: (Методы, поля, классы, интерфейсы и т. Д.)
2).@Удерживание, описывает существование аннуентации:
AntreationPolicy.Runtime Annotation будет существовать в файле байт -кодов класса и может быть получена посредством отражения во время выполнения.
Harementpolicy.class Политика удержания по умолчанию, аннотация будет существовать в файле байткода класса, но ее нельзя получить во время выполнения.
AntreationPolicy.source Annotation существует только в исходном коде и не содержит ее в файле Bytecode класса.
3).@Задокументировано, по умолчанию, аннотации не будут записаны в Javadoc, но эта аннотация может быть использована для указания, что это аннотация должна быть записана.
4). @Унаследованная мета-аннотация является аннотацией TAG, и @Inhered объясняет, что определенный аннотированный тип наследуется.
Если для класса используется тип аннотации с использованием модификации @Inhyted, аннотация будет использоваться для подкласса класса.
2. Пользовательские аннотации
Пакет com.joyfulmath.jvmexample.annnotaion; import java.lang.annotation.elementtype; импорт java.lang.annotation.retention; импорт java.lang.annotation.retentionpolicy; import java.lang.annotation.target;/*** @author deman.lu* @version @version @version @version @version @version at aversion @version @version @version at aversion. 13:36*/@target (elementtype.field) @retention (armentpolicy.runtime) public @Interface fruitName {string value () по умолчанию ";} Прежде всего, аннотация обычно требует 2 мета -аннотационных модификаций:
@Target (elementType.field)
@Retention (handentpolicy.runtime)
Конкретные функции были объяснены выше.
Все аннотации будут иметь раздел, похожий на «Func». Это можно понять как параметр аннотации.
Пакет com.joyfulmath.jvmexample.annnotaion; import com.joyfulmath.jvmexample.tracelog;/*** @author deman.lu*@version на 2016-05-23 13: 37*/public class apple {@fruitname ("Apple") String Applename; public villApplename () {tracelog ("Apple") STRIPEREMAM Журнал этого кода:
05-23 13: 39: 38.780 26792-26792/com.joyfulmath.jvmexample i/apple: displayapplename: null [at (apple.java:16)]]
Почему задание не успешно? Как назначить файл аннотации "Apple"? Как это сделать, если компилятор еще не знает.
3. Аннотация процессора
Нам также нужен процессор, чтобы объяснить, как работают аннотации, в противном случае он будет почти таким же, как и аннотации.
Благодаря отражению, содержание аннотации можно получить:
Пакет com.joyfulmath.jvmexample.annnotaion; import com.joyfulmath.jvmexample.tracelog; import java.lang.reflect.field;/*** @author deman.lu*@version на 2016-05-23 14: 08*/public fruitsfoutils {public static void getFruitInf stricezez "; Field [] fields = clazz.getDeclaredFields (); for (Field Field: Fields) {if (field.isannotationpresent (fruitname.class)) {fruitname fruitname = field.getannotation (fruitname.class); fruitnamest = fruitname.value (); traCelog.i (Fruitsnamest);Это общее использование аннотаций.
Анализ фреймворта аннотации Android
Как видно из вышесказанного, использование фреймворков аннотации по сути требует отражения.
Но если я использую структуру аннотации с функцией отражения, то я мог бы также использовать ее напрямую, это проще.
Если есть механизм, он может избежать написания большого количества дубликатов аналогичного кода, особенно во время разработки Android, соответствует большое количество FindViewByID и OnClick и других событий.
Паттерн кода согласован, но код отличается. В настоящее время использование рамки аннотации может сэкономить много времени разработки, и, конечно, это будет увеличить другие накладные расходы соответственно.
Вот пример использования ButterKnife:
@Bindstring (r.string.login_error)
String LoginErrormessage;
Это кажется очень простым, он должен назначить строку первоначальному значению, соответствующему String Res. Таким образом, вы можете сэкономить время. Конечно, это всего лишь пример.
Если вы используете другие аннотации, вы можете сэкономить много времени разработки.
Посмотрим, как это реализовано:
Пакет ButterKnife; импорт android.support.annotation.stringres; импорт java.lang.annotation.retention; импорт java.lang.annotation.target; импорт статический java.lang.annotation.elementtype.field; импорт статический java.lang.annotation.trantementpolicy. <pre> <code>* {@literal @} bindString (r.string.username_error) string usernamerrortext;* </code> </pre>*/ @harepention (class) @target (field) public @Interface bindString {/** String Resource Id Resource идентификатор, с которым поле будет связано. */@Stringres int value ();} BindString имеет только один параметр, значение, то есть присваивание значения @stringres.
То же самое, что и выше, выше, где аннотация определяется и используется, но реальное объяснение аннотации заключается в следующем: Butternifeprocessor
Частная карта <typelement, bindingclass> findandparsetargets (roundenvironment env)
Эта функция перехватывает какой -то код:
// Обработайте каждый @bindstring element.for (элемент элемента: env.getelementsannotatedwith (bindstring.class)) {if (! SuperficalValidation.validateElement (electre)) продолжить; try {parSerSourcestring (elementClassMap, eRaseDTargetNames); e);}} Найдите все элементы аннотаций BindString и начните анализировать:
private void parseresourcestring (элемент элемента, карта <typelement, bindingclass> targetclassmap, set <typelement> eRasedTargetNames) {boolean haserror = false; typelement encloseelement = (typeLement) element.getencloselement (); // подтверждение того, что мишени является строка. (! String_type.equals (element.astype (). ToString ())) {error (элемент, "@%s поля типа должен быть 'String'. (%S.%S)", bindString.class.getSimplename (), encLiseElement.getQualifiedNam RESTRICTIONS.HasError | = ISinAcepressibleViageGeneratedCode (bindString.class, "fields", element); haserror | = isBindingInwrongpackage (bindString.class, element); if (haserror) {return;} // Собирание информации на поле. element.getannotation (bindstring.class) .value (); bindingclass bindingclass = getorcreatetargetclass (targetclassmap, incloselement); FieldResourceBinding связы false);; BindingClass.Addresource (связывание); ErasedTargetNames.Add (EncLoseElement);} Сначала убедитесь, является ли элемент типом строки.
// Собирайте информацию на Field.string name = element.getSimplename (). ToString (); int id = element.getAnnotation (bindString.class) .value ();
Получите имя поля и идентификатор строки.
финал
Карта <typelement, bindingclass> TargetClassMap
Элементы и описания аннотаций хранятся один за другим на карте.
@Override Public Boolean Process (set <? Extends Typelement> Elements, vindenvironment env) {map <typelement, bindingclass> targetclassmap = findandparsetargets (env); for (map.entry <typelement, bindingclass> intpirt: intryclassmap.entryset () {typelement typelement = intryingleckclecleclecleclecleclecleclecleclecleckcleclecleclecleclecleckclecleclecleke. entry.getValue (); try {bindingClass.brewjava (). writeto (fileer);} catch (ioexception e) {error (typelement, «невозможно написать просмотр связующего для типа %s: %s», typelement, e.getMessage ());} return True;};};}; Здесь запускается структура аннотации, независимый процесс. Эта статья не будет изучать конкретные детали, просто очистите ее, это место, управляемое структурой.
Из приведенной выше информации вся информация о аннотации хранится в TargetClassMap.
Код, помеченный красный выше, должен быть ядром рамки аннотации.
Начиная с Java SE5, Java представила Apt Tool, который может предварительно обработать аннотации. Java SE6 поддерживает расширенный процессор аннотации.
И обработать его несколько раз во время компиляции. Мы можем использовать пользовательский процессор аннотации для создания нового кода Java в соответствии с правилами при составлении Java .
Javafile brewjava () {typepec.builder result = typepc.classbuilder (сгенерированный classname) .addmodifiers (public); if (isfinal) {result.addmodifiers (modifier.final);} else {result.addtypevariable (typevariablename.get ("t", targettypename));} typeName targettype = isfinal? TargetTypEname: typevariablename.get ("t"); if (hasparentBinding ()) {result.superclass (parameterizedTypEname.get (parentBinding.GeneratedClassName, targetType));} else {result.AddSuperInterface (parameterizedTypEname.get (view_binder, targetType));} result.AddMethod (createBindMethod, targetType); if (isGeneratingUnbinder ()) {result.addtype (createUnbinderclass (targetType));} else if (! ISfinal) {result.Addmethod (createBindTotargetMethod ());} return javafile.builder (GenedClassName.packagenam от ножа масла. Ключом к этому отрывку является создание нового файла.
Затем напишите соответствующий контент.