2016-10-07 4 views
0

나는 추상 클래스 myA를 확장하는 여러 클래스 A1, A2, A3를 가지고있다. 클래스 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(); 
    } 
}