2015-11-28 90 views
0

我的注释类如何在java中注释字段中设置值?

@Target({java.lang.annotation.ElementType.FIELD}) 
@Retention(RetentionPolicy.CLASS) 
public @interface Base { 
    int[] value(); 
} 

实际的类

public class Demo { 
    @Base(1) 
    public int var; 
    public int var2; 
    public void call() { 
     InjectingClass.inject(this); 
     System.out.print(var + ""); 
    } 
} 

我怎样才能设置值onevar2var不?

+2

咦?那不是你已经做过的吗?目前的代码有什么问题? – Tunaki

+0

对不起,我没有实现InjectingClass。如何实现InjectingClass? –

+0

使用'RetentionPolicy.CLASS'?非常困难(但请参阅http://google.github.io/dagger/),因为这意味着您需要一个注释处理器,它在编译时生成代码,然后“InjectingClass”几乎不做任何事情。用'.RUNTIME'代码(反射)的几行。 – zapl

回答

6

随着RUNTIME代,即当你运行它打印

1 
0 

它遍历声明的字段(即所有领域,其中声明是在这个类,如果是很简单

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
@interface Set { 
    int value(); 
} 

class Injector { 
    public static void inject(Object instance) { 
     Field[] fields = instance.getClass().getDeclaredFields(); 
     for (Field field : fields) { 
      if (field.isAnnotationPresent(Set.class)) { 
       Set set = field.getAnnotation(Set.class); 
       field.setAccessible(true); // should work on private fields 
       try { 
        field.set(instance, set.value()); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

class Demo { 
    @Set(1) 
    public int var; 
    public int var2; 

    public void call(){ 
     Injector.inject(this); 
     System.out.println(var); 
     System.out.println(var2); 
    } 
} 
public class AnnotationDemo { 
    public static void main(String[] args) { 
     new Demo().call(); 
    } 
} 

你想要这个工作与超类的继承字段,你也必须扫描这些)

检查ann的每个字段如果找到,则将该字段设置为注释中存在的值。

当你想要做同样的一个CLASS或简单SOURCE(类odd,我会用源或运行时)注释你就必须实行特殊annotation processor类由Java编译器时调用编译包含您感兴趣的注释的.java文件。在下一步中,您将生成一个.java文本源文件,其中包含执行注入的代码。该代码然后也由编译器编译,并且您在运行时的类将简单地调用生成的代码。

因此,所有你需要做的是在管理基于注释的分析编译的时候写一个类java文件像

class GeneratedInjector { 
    public static void inject(Object instance) { 
     if (instance instanceof Demo) { 
      injectDemo((Demo) instance); 
     } 
    } 
    public static void injectDemo(Demo demo) { 
     demo.var = 1; 
    } 
} 

所以在运行时,注释基本上是不存在的,并且运行的代码基本上是以下

class GeneratedInjector { 
    public static void inject(Object instance) { 
     if (instance instanceof Demo) { 
      injectDemo((Demo) instance); 
     } 
    } 
    public static void injectDemo(Demo demo) { 
     demo.var = 1; 
    } 
} 

class Injector { 
    public static void inject(Object instance) { 
     GeneratedInjector.inject(instance); 
    } 
} 

class Demo { 
    public int var; 
    public int var2; 

    public void call(){ 
     Injector.inject(this); 
     System.out.println(var); 
     System.out.println(var2); 
    } 
} 

public class AnnotationDemo { 
    public static void main(String[] args) { 
     new Demo().call(); 
    } 
} 

由于这一切直截了当普通Java,而不是反映您节省一些CPU周期。在大多数情况下,这很可能不明显,但大量的反思可能会产生影响。

https://deors.wordpress.com/2011/10/31/annotation-generators/有一些更漂亮的信息

还有第三种混合方法,这是在运行时生成字节码。这样你就可以生成一个与.java文件大致相同的.class文件。需要像https://github.com/cglib/cglib这样的字节码框架。由于您需要为Android生成.dex,因此该方法也不易与Android兼容。但我想我甚至在某个地方见过。

相关问题