변수에 주석을 추가하면 해당 변수를 통해 도달 할 수있는 객체가 아닌 해당 변수의 정적 속성이됩니다. 고려하십시오 :
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();
}
}