2013-05-29 12 views
3

다음과 같은 수업이 있습니다.리플렉션을 사용하여 수퍼 클래스를 사용하여 하위 클래스 필드 가져 오기?

public class Emp{ 

private String name; 
private String age; 

//setters and getters 

} 

아래에 한 가지 더 클래스를 추가하십시오.

public class Student extends Emp{ 
private int marks; 
//setters and getters 
} 

어쨌든 Java Reflection을 사용하여 수퍼 클래스를 사용하는 서브 클래스의 필드를 가져 오려면 어떻게해야합니까? Emp 인스턴스를 사용하여 학생 필드를 가져와야합니다.

우리는 다음과 같이 슈퍼 클래스 필드를 얻을 수 있습니다 :

subClass.getClass().getSuperclass().getDeclaredFields(); 

유사 내가 슈퍼 클래스를 사용하여 하위 클래스 필드를받을 수 있나요?

가능합니까?

감사합니다.

+1

입니다 부모 클래스 (정당하게)는 어떤 클래스가 그것을 확장하는지 알지 못합니다. – nitegazer2003

답변

2

은 이론적으로 all loaded classes 그들의 Emp에서 파생 분야를 포함하는 검사를 검색하여 매우 복잡하고 비용이 많이 드는 방법이있다. 원하는 클래스가 아직로드되지 않은 경우에도이 방법이 도움이되지 않을 수 있습니다.

3

질문에 대한 오해가 생겼을 수 있습니다. 다음과 같은 것을하고 싶습니까?

Emp e = new Student(...); 
[do something with e] 
foo = e.marks; 

예라면,이처럼 수행

foo = ((Emp)e).marks; 

그러나 당신이 그런 짓을하려는 경우 다음

Emp e = new Emp(...); 
[do something with e] 
e.marks = .... 
다음

아니, 그건 불가능하고, I Java의 객체 모델의 내부 모델이 불완전하거나 결함이 있다고 의심됩니다.

+0

+1 수업 진행 방법에 대해 혼란이있을 수 있다는 것에 동의합니다. * 인스턴스 *가 '학생'이므로 참조가 다운 캐스트 될 수도 있고 그렇지 않을 수도 있습니다. 따라서 '마크'필드가 전혀 없습니다. 반사는 어느쪽으로 든 들어 가지 않습니다. –

1

직접적으로, 당신은 그것에 도우미 방법을 써야합니다.

매개 변수로 클래스와 필드 이름 (가능하면 입력)을 취한 다음 해당 클래스에서 해당 필드를 찾습니다. 당신이 그것을 찾지 못한다면, 여러분은 클래스의 수퍼 클래스를 가져 와서 처음부터 반복하십시오. 필드를 찾거나 getSuperClass()가 null을 반환 할 때까지 (상속 트리의 루트에 도달했음을 의미)이 작업을 수행합니다.

이 예제는 개체에서 지정된 메서드을 찾아 호출하는 방법을 보여줍니다. 필드의 논리를 쉽게 추출하고 적용 할 수 있습니다.

public static Object call(final Object instance, 
          final String methodName, 
          final Class<?>[] signature, 
          final Object[] args) { 
    try { 
     if (instance == null) 
      return null; 
     Class<?> instanceClass = instance.getClass(); 
     while (instanceClass != null) { 
      try { 
       final Method method = instanceClass.getDeclaredMethod(methodName, signature); 
       if (!method.isAccessible()) 
        method.setAccessible(true); 
       return method.invoke(instance, args); 
      } catch (final NoSuchMethodException e) { 
       // ignore 
      } 
      instanceClass = instanceClass.getSuperclass(); 
     } 
    } catch (final Throwable e) { 
     return null; 
    } 
    return null; 
} 
1

원하는 것은 무엇입니까? 그러나 field.setAccesible을 사용할 때는주의하십시오.

부모 클래스 :

public class ParentClass { 
     private String parentField = "parentFieldValue"; 
     public void printFields() throws IllegalAccessException { 
      Field[] fields = getClass().getDeclaredFields(); 
      for (Field field : fields) { 
        field.setAccessible(true); 
        Object fieldValue = field.get(this); 
        if (fieldValue instanceof String) { 
          String stringValue = (String) fieldValue; 
          System.out.println(stringValue); 
        } 
      } 
     } 
} 

아이 클래스 :

public class ChildClass extends ParentClass {  
     private String childField = "childFieldValue"; 
} 

사용법 :

public class Main { 
     public static void main(String[] args) throws IllegalAccessException { 
      ParentClass pc = new ParentClass(); 
      ChildClass cc = new ChildClass(); 
      pc.printFields(); 
      cc.printFields(); 
     } 
} 
0

이 최종 솔루션입니다!

@NonNull 
    public static List<Class<?>> getSubClasses() { 
     StackTraceElement[] trace = Thread.currentThread().getStackTrace(); 
     String method = trace[3].getMethodName(); 
     if (!"<init>".equals(method)) { 
      throw new IllegalStateException("You can only call this method from constructor!"); 
     } 
     List<Class<?>> subClasses = new ArrayList<>(); 
     for (int i = 4; i < trace.length; i++) { 
      method = trace[i].getMethodName(); 
      if ("<init>".equals(method)) { 
       try { 
        subClasses.add(Class.forName(trace[i].getClassName())); 
       } catch (ClassNotFoundException e) { 
        throw new RuntimeException(e); 
       } 
      } else { 
       break; 
      } 
     } 
     return subClasses; 
    } 

은 사용의 몇 가지 예입니다 :

class a { 
public a(){ 
print(getSubClasses()); 
} 
} 
class b extends a{ 
} 
class c extends b{ 
} 

그리고 그 결과는 아니,이 때문에, 부모 클래스의 자식 클래스에 대한 정보를 얻을 수 없습니다

new a() -> [] 
new b() -> [b.class] 
new c() -> [b.class, c.class] 
관련 문제