反射我自己类的实例的注释



我有几个类A1、A2、A3,它们扩展了抽象类myA。这些类具有类B的x个字段。类B的字段使用注释Test进行注释。(测试在运行时可用(如何从B类的方法内部获取注释Test及其值。

public class A1 extends myA{
    @Test("all")
    private B b1;
    @Test("none")
    private B b2;
    @Test("none")
    private B b3;
    //....
    public void interact(){
        b2.doSomethingBasedOnMyAnnotation();
    }
}
public class A2 extends myA{
    @Test("none")
    private B b;
    //....
}
public class B{
     public void doSomethingBasedOnMyAnnotation(){
        // How to reach the Annotation from here ?
     }
}
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface Test{
    String value() default "all";
}

当您在变量上放置注释时,它将成为该变量的静态属性,而不是您可以通过该变量访问的对象的静态属性。考虑:

public class A1 extends myA{
    @Test("all")
    private B b1=new B();
    @Test("none")
    private B b2=b1;
    //....
    public void interact(){
        // this
        b2.doSomethingBasedOnMyAnnotation();
        // is exactly the same as
        b1.doSomethingBasedOnMyAnnotation();
    }
}

假设其中包含一个带注释的变量是无效的。
怎么样new B().doSomethingBasedOnMyAnnotation()

由于字段是在编译时解析的,所以在所需的操作中无论如何都没有抽象。如果您知道要调用b2.doSomethingBasedOnMyAnnotation();,那么您已经知道要使用哪个字段,并且将b2的注释值作为参数提供给被调用的方法是没有问题的,而不是期望接收器神奇地发现。例如

public class B{
    public void doSomething(String arg){
    }
}
public class A1 extends myA{
    @Test("all")
    private B b1;
    @Test("none")
    private B b2;
    //....
    public void interact(){
        b1.doSomething(get("b1"));
        b2.doSomething(get("b2"));
    }
    static String get(String fieldName) {
        try {
            return A1.class.getDeclaredField(fieldName)
                .getAnnotation(Test.class).value();
        } catch(NoSuchFieldException ex) {
            throw new IllegalStateException(ex);
        }
    }
}

尽管我们可以在没有反射的情况下愉快地工作:

public class A1 extends myA{
    static final String TEST_B1="all";
    @Test(TEST_B1)
    private B b1;
    static final String TEST_B2="none";
    @Test(TEST_B2)
    private B b2;
    static final String TEST_B3="none";
    @Test(TEST_B3)
    private B b3;
    //....
    public void interact(){
        b1.doSomething(TEST_B1);
        b2.doSomething(TEST_B2);
    }
}

如果您想确保调用者不会意外地传递错误的参数,请使用封装:

public final class EncapsulatedB {
    final String testValue;
    B b;
    EncapsulatedB(String value) {
        this(value, null);
    }
    EncapsulatedB(String value, B initialB) {
        testValue=value;
        b=initialB;
    }
    public B getB() {
        return b;
    }
    public void setB(B b) {
        this.b = b;
    }
    public void doSomething() {
        b.doSomething(testValue);
    }
}
public class A1 extends myA{
    private final EncapsulatedB b1=new EncapsulatedB("all");
    private final EncapsulatedB b2=new EncapsulatedB("none");
    private final EncapsulatedB b3=new EncapsulatedB("none");
    //....
    public void interact(){
        b1.doSomething();
        b2.doSomething();
    }
}

相关内容

  • 没有找到相关文章

最新更新