Java-аннотация
В языке программирования Java аннотация представляет собой форму синтаксических метаданных , которые можно добавлять в исходный код Java . [1] Классы , методы , переменные , параметры и пакеты Java могут быть аннотированы. Как и теги Javadoc , аннотации Java можно читать из исходных файлов. В отличие от тегов Javadoc , аннотации Java также можно встраивать и читать из файлов классов Java, созданных компилятором Java . сохранять аннотации Это позволяет виртуальной машине Java во время выполнения и читать их посредством отражения . [2] В Java можно создавать метааннотации из существующих. [3]
История
[ редактировать ]Платформа Java имеет различные механизмы специальных аннотаций, например transient
модификатор, или @Deprecated
тег javadoc. Запрос на спецификацию Java JSR-175 представил возможность аннотаций общего назначения (также известных как метаданные ) в процессе сообщества Java в 2002 году; он получил одобрение в сентябре 2004 года. [4]
Аннотации стали доступны в самом языке, начиная с версии 1.5 Java Development Kit (JDK). apt
инструмент предоставил временный интерфейс для обработки аннотаций во время компиляции в JDK версии 1.5; он был интегрирован в компилятор javac JSR-269 формализовал это, и в версии 1.6 .
Встроенные аннотации
[ редактировать ]Java определяет набор аннотаций, встроенных в язык. Из семи стандартных аннотаций три являются частью java.lang , а остальные четыре импортированы из java.lang.annotation. [5] [6]
Аннотации, применяемые к коду Java:
@Override
— Проверяет, что метод является переопределением . Вызывает ошибку компиляции , если метод не найден ни в одном из родительских классов или реализованных интерфейсов .@Deprecated
- Отмечает метод как устаревший. Вызывает предупреждение компиляции, если используется метод.@SuppressWarnings
— Указывает компилятору подавлять предупреждения времени компиляции, указанные в параметрах аннотации.
Аннотации, применяемые к другим аннотациям (также известные как «метааннотации»):
@Retention
— Указывает, как сохраняется отмеченная аннотация: только в коде, скомпилирована в класс или доступна во время выполнения посредством отражения.@Documented
- Отмечает другую аннотацию для включения в документацию.@Target
— Отмечает другую аннотацию, чтобы ограничить тип элементов Java, к которым может применяться эта аннотация.@Inherited
— Отмечает другую аннотацию, которая будет унаследована подклассами аннотированного класса (по умолчанию аннотации не наследуются подклассами).
Начиная с Java 7, в язык были добавлены три дополнительные аннотации.
@SafeVarargs
— Подавление предупреждений для всех вызывающих методов или конструкторов с помощью параметра generics varargs , начиная с Java 7.@FunctionalInterface
— Указывает, что объявление типа предназначено для использования в качестве функционального интерфейса , начиная с Java 8.@Repeatable
— Указывает, что аннотация может применяться более одного раза к одному и тому же объявлению, начиная с Java 8.
Пример
[ редактировать ]Встроенные аннотации
[ редактировать ]Этот пример демонстрирует использование @Override
аннотация. Он дает указание компилятору проверить родительские классы на наличие соответствующих методов. В этом случае генерируется ошибка, поскольку gettype()
метод класса Cat фактически не переопределяет getType()
желательно класса Animal Like из-за несовпадающего регистра . Если @Override
аннотации отсутствовали, новый метод имени gettype()
будет создан в классе Cat.
public class Animal {
public void speak() {
}
public String getType() {
return "Generic animal";
}
}
public class Cat extends Animal {
@Override
public void speak() { // This is a good override.
System.out.println("Meow.");
}
@Override
public String gettype() { // Compile-time error due to typo: should be getType() not gettype().
return "Cat";
}
}
Пользовательские аннотации
[ редактировать ]Объявления типов аннотаций аналогичны обычным объявлениям интерфейсов. Знак (@) предшествует ключевому слову «интерфейс».
// @Twizzle is an annotation to method toggle().
@Twizzle
public void toggle() {
}
// Declares the annotation Twizzle.
public @interface Twizzle {
}
Аннотации могут включать набор пар ключ-значение, которые моделируются как методы типа аннотации. Каждое объявление метода определяет элемент типа аннотации. Объявления методов не должны иметь никаких параметров или предложения throws. Типы возвращаемых значений ограничены примитивами , строками , классами, перечислениями , аннотациями и массивами предыдущих типов. Методы могут иметь значения по умолчанию .
// Same as: @Edible(value = true)
@Edible(true)
Item item = new Carrot();
public @interface Edible {
boolean value() default false;
}
@Author(first = "Oompah", last = "Loompah")
Book book = new Book();
public @interface Author {
String first();
String last();
}
Сами аннотации могут быть снабжены аннотациями, указывающими, где и когда их можно использовать:
@Retention(RetentionPolicy.RUNTIME) // Make this annotation accessible at runtime via reflection.
@Target({ElementType.METHOD}) // This annotation can only be applied to class methods.
public @interface Tweezable {
}
Компилятор резервирует набор специальных аннотаций (в том числе @Deprecated
, @Override
и @SuppressWarnings
) для синтаксических целей.
Аннотации часто используются платформами как способ удобного применения поведения к определяемым пользователем классам и методам, которые в противном случае должны быть объявлены во внешнем источнике (например, в файле конфигурации XML) или программно (с помощью вызовов API). Ниже приведен, например, аннотированный класс данных JPA :
@Entity // Declares this an entity bean
@Table(name = "people") // Maps the bean to SQL table "people"
public class Person implements Serializable {
@Id // Map this to the primary key column.
@GeneratedValue(strategy = GenerationType.AUTO) // Database will generate new primary keys, not us.
private Integer id;
@Column(length = 32) // Truncate column values to 32 characters.
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Аннотации не являются вызовами методов и сами по себе ничего не делают. Вместо этого объект класса передается реализации JPA во время выполнения , которая затем извлекает аннотации для создания объектно-реляционного сопоставления .
Полный пример приведен ниже:
package com.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,
ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE,
ElementType.PACKAGE,ElementType.FIELD,ElementType.LOCAL_VARIABLE})
@Inherited
public @interface Unfinished {
public enum Priority { LOW, MEDIUM, HIGH }
String value();
String[] changedBy() default "";
String[] lastChangedBy() default "";
Priority priority() default Priority.MEDIUM;
String createdBy() default "James Gosling";
String lastChanged() default "2011-07-08";
}
package com.annotation;
public @interface UnderConstruction {
String owner() default "Patrick Naughton";
String value() default "Object is Under Construction.";
String createdBy() default "Mike Sheridan";
String lastChanged() default "2011-07-08";
}
package com.validators;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import com.annotation.UnderConstruction;
import com.annotation.Unfinished;
import com.annotation.Unfinished.Priority;
import com.util.Util;
@UnderConstruction(owner="Jon Doe")
public class DateValidator implements Validator {
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException {
String date = (String) value;
String errorLabel = "Please enter a valid date.";
if (!component.getAttributes().isEmpty()) {
errorLabel = (String) component.getAttributes().get("errordisplayval");
}
if (!Util.validateAGivenDate(date)) {
@Unfinished(changedBy = "Steve",
value = "whether to add message to context or not, confirm",
priority = Priority.HIGH
)
FacesMessage message = new FacesMessage();
message.setSeverity(FacesMessage.SEVERITY_ERROR);
message.setSummary(errorLabel);
message.setDetail(errorLabel);
throw new ValidatorException(message);
}
}
}
Обработка
[ редактировать ]Когда исходный код Java компилируется, аннотации могут обрабатываться подключаемыми модулями компилятора, называемыми процессорами аннотаций. Процессоры могут создавать информационные сообщения или создавать дополнительные исходные файлы или ресурсы Java, которые, в свою очередь, могут быть скомпилированы и обработаны. Однако процессоры аннотаций не могут изменять сам аннотированный код. (Модификации кода могут быть реализованы с использованием методов, выходящих за рамки спецификации языка Java.) Компилятор Java условно сохраняет метаданные аннотации в файлах классов, если аннотация имеет RetentionPolicy
из CLASS
или RUNTIME
. Позже JVM или другие программы могут искать метаданные, чтобы определить, как взаимодействовать с элементами программы или изменить их поведение.
Помимо обработки аннотации с помощью процессора аннотаций, Java-программист может написать собственный код, использующий отражение для обработки аннотации. Java SE 5 поддерживает новый интерфейс, определенный в java.lang.reflect
упаковка. Этот пакет содержит интерфейс под названием AnnotatedElement
который реализуется классами отражения Java, включая Class
, Constructor
, Field
, Method
, и Package
. Реализации этого интерфейса используются для представления аннотированного элемента программы, работающей в данный момент на виртуальной машине Java. Этот интерфейс позволяет рефлективно читать аннотации.
The AnnotatedElement
интерфейс обеспечивает доступ к аннотациям, имеющим RUNTIME
удержание. Этот доступ обеспечивается getAnnotation
, getAnnotations
, и isAnnotationPresent
методы. Поскольку типы аннотаций компилируются и сохраняются в файлах байт-кода, как и классы, аннотации, возвращаемые этими методами, можно запрашивать так же, как и любой обычный объект Java. Полный пример обработки аннотации приведен ниже:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// This is the annotation to be processed
// Default for Target is all Java Elements
// Change retention policy to RUNTIME (default is CLASS)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeHeader {
// Default value specified for developer attribute
String developer() default "Unknown";
String lastModified();
String [] teamMembers();
int meaningOfLife();
}
// This is the annotation being applied to a class
@TypeHeader(developer = "Bob Bee",
lastModified = "2013-02-12",
teamMembers = { "Ann", "Dan", "Fran" },
meaningOfLife = 42)
public class SetCustomAnnotation {
// Class contents go here
}
// This is the example code that processes the annotation
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
public class UseCustomAnnotation {
public static void main(String [] args) {
Class<SetCustomAnnotation> classObject = SetCustomAnnotation.class;
readAnnotation(classObject);
}
static void readAnnotation(AnnotatedElement element) {
try {
System.out.println("Annotation element values: \n");
if (element.isAnnotationPresent(TypeHeader.class)) {
// getAnnotation returns Annotation type
Annotation singleAnnotation =
element.getAnnotation(TypeHeader.class);
TypeHeader header = (TypeHeader) singleAnnotation;
System.out.println("Developer: " + header.developer());
System.out.println("Last Modified: " + header.lastModified());
// teamMembers returned as String []
System.out.print("Team members: ");
for (String member : header.teamMembers())
System.out.print(member + ", ");
System.out.print("\n");
System.out.println("Meaning of Life: "+ header.meaningOfLife());
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
См. также
[ редактировать ]- Джакарта Аннотации
- Атрибуты CLI
- Ява
- виртуальная машина Java
- Модельно-ориентированная архитектура
- Декораторы Python , вдохновленные аннотациями Java, которые имеют аналогичный синтаксис.
Ссылки
[ редактировать ]- ^ «Аннотации» . Сан Микросистемс . Архивировано из оригинала 25 сентября 2011 г. Проверено 30 сентября 2011 г. .
- ^ Сан Микросистемы (2005). Спецификация языка Java(TM) (3-е изд.). Прентис Холл . ISBN 0-321-24678-0 . .
- ^ Дэйр Обасанджо (2007). «СРАВНЕНИЕ ЯЗЫКА ПРОГРАММИРОВАНИЯ C# MICROSOFT С ЯЗЫКОМ ПРОГРАММИРОВАНИЯ JAVA SUN MICROSYSTEMS: Аннотации метаданных» . Дэйр Обасанджо. Архивировано из оригинала 19 сентября 2012 г. Проверено 20 сентября 2012 г.
- ^ Трус, Дэнни (2 ноября 2006 г.). «JSR 175: средство метаданных для языка программирования JavaTM» . Процесс сообщества Java . Проверено 5 марта 2008 г.
- ^ «Предопределенные типы аннотаций» . Корпорация Оракл . Проверено 17 декабря 2016 г.
- ^ «Встроенные аннотации: стандартные аннотации» . Проверено 17 декабря 2016 г.
Внешние ссылки
[ редактировать ]- Введение в аннотации Java 6 на сайте Sun Developer Network
- Введение в Java-аннотации М.М. Ислама Чистого
- Шринивасан, Кришна (11 августа 2007 г.). «Аннотации в Java 5.0» . JavaBeat . Архивировано из оригинала 31 мая 2015 года.
- Хант, Джон (24 февраля 2006 г.). «Об аннотациях Java» . Регистр .
- «Как создавать и реализовывать собственные аннотации в Java?» . Так много слов . 15 февраля 2014 г. Архивировано из оригинала 23 февраля 2014 г.
- «Урок по аннотациям Java с примерами» . Учебный стол . 9 октября 2014 г.
- Такор, Вики (13 октября 2015 г.). «Понимание аннотаций в Java» . Java на примерах .