2016-10-07 57 views
0

我有幾個擴展抽象類myA的類A1,A2,A3。這些類具有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"; 
} 

回答

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