Spec-Zone .ru
спецификации, руководства, описания, API
|
Другие API требуют, ", чтобы файлы стороны” сохранялись параллельно с программами. Например JavaBeans требует a BeanInfo
class, который будет сохраняться параллельно с бобом, и Предприятием JavaBeans (EJB), требует дескриптора развертывания. Это было бы более удобным и менее подверженным ошибкам, если бы информация в этих файлах стороны сохранялась как аннотации в программе непосредственно.
У платформы Java всегда были различные оперативные механизмы аннотации. Например transient
модификатор является оперативной аннотацией, указывающей, что поле должно быть проигнорировано подсистемой сериализации, и @deprecated
тег javadoc является оперативной аннотацией, указывающей, что метод больше не должен использоваться. У платформы есть аннотация общего назначения (также известный как метаданные) средство, которое разрешает Вам определять и использовать свои собственные типы аннотации. Средство состоит из синтаксиса для того, чтобы объявить типы аннотации, синтаксис для того, чтобы аннотировать объявления, API для того, чтобы считать аннотации, представление файла class для аннотаций, и аннотации, обрабатывающей поддержку, оказанную javac
инструмент.
Аннотации непосредственно не влияют на семантику программы, но они действительно влияют на способ, которым программы обрабатываются инструментами и библиотеками, которые могут поочередно влиять на семантику рабочей программы. Аннотации могут быть считаны из исходных файлов, файлов class, или отражающим образом во время выполнения.
Дополнение аннотаций javadoc теги. Вообще, если разметка предназначается, чтобы влиять или произвести документацию, это должен, вероятно, быть тег javadoc; иначе, это должна быть аннотация.
Типичные прикладные программисты никогда не должны будут определять тип аннотации, но не трудно сделать так. Описания типа аннотации подобны нормальным объявлениям интерфейса. Знак at-sign (@
) предшествует interface
ключевое слово. Каждое объявление метода определяет элемент типа аннотации. У объявлений метода не должно быть никаких параметров или a throws
пункт. Возвратитесь типы ограничиваются примитивам, String
, Class
, перечисления, аннотации, и массивы предыдущих типов. У методов могут быть значения по умолчанию. Вот описание типа аннотации в качестве примера:
/** * Describes the Request-For-Enhancement(RFE) that led * to the presence of the annotated API element. */ public @interface RequestForEnhancement { int id(); String synopsis(); String engineer() default "[unassigned]"; String date() default "[unimplemented]"; }
Как только тип аннотации определяется, можно использовать его, чтобы аннотировать объявления. Аннотация является специальным видом модификатора, и может использоваться где угодно что другие модификаторы (такой как public
, static
, или final
) может использоваться. Условно, аннотации предшествуют другим модификаторам. Аннотации состоят из знака at-sign (@
) сопровождаемый типом аннотации и заключенным в скобки списком пар значения элемента. Значения должны быть константами времени компиляции. Вот объявление метода с аннотацией, соответствующей типу аннотации, объявленному выше:
@RequestForEnhancement( id = 2868724, synopsis = "Enable time-travel", engineer = "Mr. Peabody", date = "4/1/3007" ) public static void travelThroughTime(Date destination) { ... }
Тип аннотации без элементов называют типом аннотации маркера, например:
/** * Indicates that the specification of the annotated API element * is preliminary and subject to change. */ public @interface Preliminary { }
Допустимо опустить круглые скобки в аннотациях маркера, как показано ниже:
@Preliminary public class TimeTravel { ... }
В аннотациях с единственным элементом нужно назвать элемент value
, как показано ниже:
/** * Associates a copyright notice with the annotated API element. */ public @interface Copyright { String value(); }
Это допустимо опустить имя элемента и равняется знаку (=
) в одноэлементной аннотации, имя элемента которой value
, как показано ниже:
@Copyright("2002 Yoyodyne Propulsion Systems") public class OscillationOverthruster { ... }
Чтобы связать все это, мы создадим простую основанную на аннотации тестовую платформу. Сначала мы нуждаемся в типе аннотации маркера, чтобы указать, что метод является методом испытаний, и должен быть выполнен инструментом тестирования:
import java.lang.annotation.*; /** * Indicates that the annotated method is a test method. * This annotation should be used only on parameterless static methods. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { }
Отметьте, что описание типа аннотации самостоятельно аннотируется. Такие аннотации вызывают метааннотациями. Первое (@Retention(RetentionPolicy.RUNTIME)
) указывает, что аннотации с этим типом должны быть сохранены VM, таким образом, они могут быть считаны отражающим образом во времени выполнения. Второе (@Target(ElementType.METHOD)
) указывает, что этот тип аннотации может использоваться, чтобы аннотировать только объявления метода.
Вот пример программы, некоторые из чей методов аннотируются вышеупомянутым интерфейсом:
public class Foo { @Test public static void m1() { } public static void m2() { } @Test public static void m3() { throw new RuntimeException("Boom"); } public static void m4() { } @Test public static void m5() { } public static void m6() { } @Test public static void m7() { throw new RuntimeException("Crash"); } public static void m8() { } }
Вот инструмент тестирования:
import java.lang.reflect.*; public class RunTests { public static void main(String[] args) throws Exception { int passed = 0, failed = 0; for (Method m : Class.forName(args[0]).getMethods()) { if (m.isAnnotationPresent(Test.class)) { try { m.invoke(null); passed++; } catch (Throwable ex) { System.out.printf("Test %s failed: %s %n", m, ex.getCause()); failed++; } } } System.out.printf("Passed: %d, Failed %d%n", passed, failed); } }
Инструмент берет имя class в качестве параметра командной строки и выполняет итерации по всем методам именованного class, пытающегося вызвать каждый метод, который аннотируется Test
тип аннотации (определенный выше). Отражающий запрос, чтобы узнать, есть ли у метода a Test
аннотация выделяется в зеленом. Если вызов метода испытаний выдает исключение, тест, как считают, перестал работать, и отчет отказа печатается. Наконец, сводка печатается, показывая число тестов, которые передали и перестали работать. Вот то, как это смотрит, когда Вы работаете на инструменте тестирования Foo
программа (выше):
$ java RunTests Foo Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash Passed: 2, Failed 2В то время как этот инструмент тестирования является ясно игрушкой, он демонстрирует питание аннотаций и мог легко быть расширен, чтобы преодолеть его ограничения.