代码之家  ›  专栏  ›  技术社区  ›  akuhn

在Java中使用默认值创建Annotation实例

  •  39
  • akuhn  · 技术社区  · 17 年前

    如何创建以下注释的实例(将所有字段设置为默认值)。

        @Retention( RetentionPolicy.RUNTIME )
        public @interface Settings {
                String a() default "AAA";
                String b() default "BBB";
                String c() default "CCC";
        }
    

    我试过了 new Settings() ,但这似乎行不通。。。

    7 回复  |  直到 17 年前
        1
  •  41
  •   Ralph    6 年前

    要创建实例,您需要创建一个实现以下功能的类:

    例如: public class MySettings implements Annotation, Settings

    但你需要特别注意 对的 实施 equals hashCode 根据 Annotation 界面。 http://download.oracle.com/javase/1.5.0/docs/api/java/lang/annotation/Annotation.html

    如果您不想一次又一次地实现此功能,请查看 javax.enterprise.util.AnnotationLiteral 类。 这是CDI(上下文依赖注入)-API的一部分。 (@see code)

    要获取默认值,您可以使用akuhn(以前称为:Adrian)描述的方法。 Settings.class.getMethod("a").getDefaultValue()

        2
  •  38
  •   akuhn    17 年前

    您无法创建实例,但至少可以获取默认值

    Settings.class.getMethod("a").getDefaultValue()
    Settings.class.getMethod("b").getDefaultValue()
    Settings.class.getMethod("c").getDefaultValue()
    

    然后,可以使用动态代理返回默认值。据我所知,这也是Java本身处理注释的方式。

    class Defaults implements InvocationHandler {
      public static <A extends Annotation> A of(Class<A> annotation) {
        return (A) Proxy.newProxyInstance(annotation.getClassLoader(),
            new Class[] {annotation}, new Defaults());
      }
      public Object invoke(Object proxy, Method method, Object[] args)
          throws Throwable {
        return method.getDefaultValue();
      }
    }
    
    Settings s = Defaults.of(Settings.class);
    System.out.printf("%s\n%s\n%s\n", s.a(), s.b(), s.c());
    
        3
  •  28
  •   emory    11 年前

    我编译并运行了下面的代码,结果令人满意。

    class GetSettings {
        public static void main (String[] args){
          @Settings final class c { }
          Settings settings = c.class.getAnnotation(Settings.class);
          System.out.println(settings.aaa());
        }
    }
    
        4
  •  3
  •   ex0b1t    12 年前

    遇到同样的问题,我按如下方式解决了。

    public static FieldGroup getDefaultFieldGroup() {
        @FieldGroup
        class settring {
        }
        return settring.class.getAnnotation(FieldGroup.class);
    }
    
        5
  •  2
  •   mindas    9 年前

    如果你能负担得起改变身体的费用,还有另一种解决方案 Settings 类别:

    @Retention( RetentionPolicy.RUNTIME )
    public @interface Settings {
            String DEFAULT_A = "AAA";
            String DEFAULT_B = "BBB";
            String DEFAULT_C = "CCC";
    
            String a() default DEFAULT_A;
            String b() default DEFAULT_B;
            String c() default DEFAULT_C;
    }
    

    然后你可以简单地引用 Settings.DEFAULT_A (是的,一个更好的名字会有所帮助!)。

        6
  •  1
  •   Jason Plank Maksim Kondratyuk    14 年前

    如果与一种方法一起使用:

    @Settings
    public void myMethod() {
    }
    

    现在,您的注释已使用默认值初始化。

        7
  •  0
  •   Thomas Darimont    11 年前

    这适用于Sun/Oracle Java 5,6,7,8:(但由于涉及Sun类,可能会与Java 9中断)。 //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)