Это работает с Sun / Oracle Java 5,6,7,8: (но потенциально может порвать с Java 9 из-за использования классов Sun).
// edit Только что проверил, что это все еще работает с OpenJDK 9b59.
package demo;
import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class AnnotationProxyExample
{
public static void main(String[] args)
{
System.out.printf("Custom annotation creation: %s%n",
createAnnotationInstance(Collections.singletonMap("value", "required"), Example.class));
System.out.printf("Traditional annotation creation: %s%n",
X.class.getAnnotation(Example.class));
}
private static <A extends Annotation> A createAnnotationInstance(Map<String, Object> customValues, Class<A> annotationType)
{
Map<String, Object> values = new HashMap<>();
//Extract default values from annotation
for (Method method : annotationType.getDeclaredMethods())
{
values.put(method.getName(), method.getDefaultValue());
}
//Populate required values
values.putAll(customValues);
return (A) AnnotationParser.annotationForMap(annotationType, values);
}
@Example("required")
static class X
{
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Example
{
String value();
int foo() default 42;
boolean bar() default true;
}
}
Выход:
Custom annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)
Traditional annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)