Ответ 1
Я никогда не использовал его на практике, но, что вы получаете, вы можете использовать классы в качестве замены ваших аннотаций.
Позвольте создать искусственный пример. Скажем, у нас есть генератор документации. Он читает аннотацию @Docu
от заданных классов и печатает атрибут description
. Вот так:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
public class DokuGenerator {
public static void main(String[] args) throws Exception {
new DokuGenerator(StaticClass.class, StaticClass2.class);
}
public DokuGenerator(Class<?>... classesToDokument) throws Exception {
List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
printDocumentation(documentAnnotations);
}
private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
throws Exception {
List<Docu> result = new ArrayList<Docu>();
for (Class<?> c : classesToDokument)
if (c.isAnnotationPresent(Docu.class))
result.add(c.getAnnotation(Docu.class));
return result;
}
private void printDocumentation(List<Docu> toDocument) {
for (Docu m : toDocument)
System.out.println(m.description());
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
String description();
}
@Docu(description = "This is a static class!")
class StaticClass {
}
@Docu(description = "This is another static class!")
class StaticClass2 {
}
Печать
This is a static class!
This is another static class!
То, что мы хотим сделать, состоит в том, что класс может быть не только статически аннотирован, но и может добавлять информацию о времени выполнения в документацию. Мы очень рады использовать аннотацию @Docu
большую часть времени, но есть особые случаи, которые мы хотим получить специальную документацию. Возможно, мы захотим добавить документацию производительности для некоторых методов. Мы можем сделать это, разрешив классу реализовать аннотацию. Генератор сначала проверяет аннотацию и, если нет, проверяет, реализует ли класс аннотацию. Если это так, он добавляет класс в список аннотаций.
Подобно этому (только две дополнительные строки кода в генераторе):
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DokuGenerator {
public static void main(String[] args) throws Exception {
new DokuGenerator(StaticClass.class, StaticClass2.class,
DynamicClass.class);
}
public DokuGenerator(Class<?>... classesToDokument) throws Exception {
List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
printDocumentation(documentAnnotations);
}
private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
throws Exception {
List<Docu> result = new ArrayList<Docu>();
for (Class<?> c : classesToDokument)
if (c.isAnnotationPresent(Docu.class))
result.add(c.getAnnotation(Docu.class));
else if (Arrays.asList(c.getInterfaces()).contains(Docu.class))
result.add((Docu) c.newInstance());
return result;
}
private void printDocumentation(List<Docu> toDocument) {
for (Docu m : toDocument)
System.out.println(m.description());
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
String description();
}
@Docu(description = "This is a static class!")
class StaticClass {
}
@Docu(description = "This is another static class!")
class StaticClass2 {
}
class DynamicClass implements Docu {
public DynamicClass() {
try {
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
// ignore exception to make debugging a little harder
}
}
@Override
public String description() {
long millis = System.currentTimeMillis();
new DynamicClass();
millis = System.currentTimeMillis() - millis;
return "This is a dynamic class. I run on "
+ System.getProperty("os.name")
+ ". The construction of an instance of this class run for "
+ millis + " milliseconds.";
}
@Override
public Class<? extends Annotation> annotationType() {
return Docu.class;
}
}
Выход:
This is a static class!
This is another static class!
This is a dynamic class. I run on Windows XP. The construction of an instance of this class run for 47 milliseconds.
Вам не нужно сильно изменять генератор кода, потому что вы можете использовать класс в качестве замены аннотации.
Другой пример, который должен быть структурой, которая использует аннотации или XML как конфигурацию. У вас может быть один процессор, который работает с аннотациями. Если вы используете XML как конфигурацию, вы можете создавать экземпляры классов, которые реализуют аннотации, и ваш процессор работает над ними без единого изменения! (конечно, есть и другие способы достижения такого же эффекта, но это ОДИН способ сделать это)