倚天杖
在OSX上测试过。效果很好。由于我还需要在运行时更改注释值,所以我重新讨论了这个问题。下面是@assylias方法的修改版本(非常感谢您的启发)。/**
* Changes the annotation value for the given key of the given annotation to newValue and returns
* the previous value.
*/@SuppressWarnings("unchecked")public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){
Object handler = Proxy.getInvocationHandler(annotation);
Field f;
try {
f = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
f.setAccessible(true);
Map<String, Object> memberValues;
try {
memberValues = (Map<String, Object>) f.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Object oldValue = memberValues.get(key);
if (oldValue == null || oldValue.getClass() != newValue.getClass()) {
throw new IllegalArgumentException();
}
memberValues.put(key,newValue);
return oldValue;}用法示例:@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface ClassAnnotation {
String value() default "";}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface FieldAnnotation {
String value() default "";}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MethodAnnotation {
String value() default "";}@ClassAnnotation("class test")public static class TestClass{
@FieldAnnotation("field test")
public Object field;
@MethodAnnotation("method test")
public void method(){
}}public static void main(String[] args) throws Exception {
final ClassAnnotation classAnnotation = TestClass.class.getAnnotation(ClassAnnotation.class);
System.out.println("old ClassAnnotation = " + classAnnotation.value());
changeAnnotationValue(classAnnotation, "value", "another class annotation value");
System.out.println("modified ClassAnnotation = " + classAnnotation.value());
Field field = TestClass.class.getField("field");
final FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class);
System.out.println("old FieldAnnotation = " + fieldAnnotation.value());
changeAnnotationValue(fieldAnnotation, "value", "another field annotation value");
System.out.println("modified FieldAnnotation = " + fieldAnnotation.value());
Method method = TestClass.class.getMethod("method");
final MethodAnnotation methodAnnotation = method.getAnnotation(MethodAnnotation.class);
System.out.println("old MethodAnnotation = " + methodAnnotation.value());
changeAnnotationValue(methodAnnotation, "value", "another method annotation value");
System.out.println("modified MethodAnnotation = " + methodAnnotation.value());}这种方法的优点是不需要创建新的注释实例。因此,不需要预先知道具体的注释类。另外,副作用应该是最小的,因为原始的注释实例保持不变。用Java 8进行测试。