Я никогда не использовал это на практике, но вы получаете то, что вы можете использовать классы в качестве замены для ваших аннотаций.
Давайте создадим искусственный пример. Скажем, у нас есть генератор документации. Он читает аннотацию @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 в качестве конфигурации, вы можете генерировать экземпляры классов, которые реализуют аннотации, и ваш процессор работает с ними без единого изменения! (конечно, есть другие способы достижения того же эффекта, но это ОДИН способ сделать это)