2016-10-07 12 views
0

У меня есть несколько классов A1, A2, A3, которые расширяют абстрактный класс myA. Эти классы имеют поля x класса B. Поля класса B аннотируются с помощью теста аннотации. (Тест доступен во время выполнения). Как получить тест аннотации и его значение из метода класса B.Отразить аннотацию экземпляра моего собственного класса

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"; 
} 

ответ

0

Когда вы помещаете аннотацию на переменную, она становится статическим свойством этой переменной, а не объектом, который вы можете достичь через эту переменную. Рассмотрим:

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(); 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^