2017-03-14 9 views
0

상속을 사용하여 클래스 생성자에서 리플렉션을 만드는 데 문제가 있습니다. 특히 모든 속성 값을 얻고 싶습니다.상속을 사용한 생성자에서의 리플렉션 (Java)

import java.lang.reflect.Field; 

public class SubInitProblem { 
    public static void main(String[] args) throws IllegalAccessException { 
    Child p = new Child(); 
    } 
} 

class Parent { 
    public int parentVar = 888888; 

    public Parent() throws IllegalAccessException { 
    this.showFields(); 
    } 

    public void showFields() throws IllegalAccessException { 
    for (Field f : this.getClass().getFields()) { 
     System.out.println(f + ": " + f.get(this)); 
    } 
    } 
} 

class Child extends Parent { 
    public int childVar = 999999; 

    public Child() throws IllegalAccessException { 
    super(); 
    } 
} 

childVar가 0이 표시됩니다 :

public int Child.childVar: 0 
public int Parent.parentVar: 888888 

를 아직 초기화되지 때문에 여기

이 작동하지 않는 순진 구현을위한 데모입니다.

import java.lang.reflect.Field; 

public class SubInitSolution { 
    public static void main(String[] args) throws IllegalAccessException { 
    SolChild p = SolChild.make(); 
    } 
} 

class SolParent { 
    public int parentVar = 888888; 

    protected SolParent() { 
    } 

    public static <T extends SolParent> T make() throws IllegalAccessException { 
    SolParent inst = new SolParent(); 
    inst.showFields(); 
    return (T) inst; 
    } 

    public void showFields() throws IllegalAccessException { 
    for (Field f : this.getClass().getFields()) { 
     System.out.println(f + ": " + f.get(this)); 
    } 
    } 

} 

class SolChild extends SolParent { 
    public int childVar = 999999; 

    public SolChild() throws IllegalAccessException { 
    } 
} 

그러나 make는 반환하지 않기 때문에 문제가 해결되지 않습니다

그래서 내가 직접 생성자를 사용하지해야하지만 오히려 수 있도록 전체 생성자 다음 사용 showFields을 것 같아요 서브 클래스의 올바른 형태 문제는 new SolParent();입니다.

이 문제를 해결하는 가장 좋은 방법은 무엇입니까? showFields을 실행하기 위해 모든 하위 클래스가 필요하지만 명시 적으로 그 서브 클래스에 의존 할 수는 없습니다. 후자는 공공 필드를 처리하기 때문에, 내가하지 Class.getFields()Class.getDeclaredFields()을 사용

public void showFields() throws IllegalAccessException { 
    Class<?> clz = this.getClass(); 
    while(clz != Object.class) { 
     for (Field f : clz.getDeclaredFields()) { 
      f.setAccessible(true); 
      System.out.println(f + ": " + f.get(this)); 
     } 
     clz=clz.getSuperclass(); 
    } 
} 

참고 :

+0

두 번째 예제에서 왜'make' 메소드를 구현합니까? 왜 그냥 'new SolChild(). showFields();'를하지 않을까요? – ToYonos

+3

생성자에서 그런 메소드를 호출하지 마십시오. 초기화에 기여하지 않으므로 생성자에 속하지 않습니다. –

+0

@ ToYonos 그렇다면 내 수업을 사용하는 사람들은 그 일을 잊을 수도 있기 때문에 – Mark

답변

2

귀하의 showFields 방법은 이런 식으로 뭔가를 클래스 계층 구조를 탐색 할 필요가있다.


그리고 이것은 당신이 일반적인 방법으로 클래스를 만들 수있는 방법입니다 : 이것은 단지 SolParent 당신의 하위 유형이 공개 인자없는 생성자가있는 경우 작동합니다

public static <T extends SolParent> T make(Class<T> type) throws Exception { 
    Constructor<T> constructor = type.getDeclaredConstructor(); 
    constructor.setAccessible(true); 
    T inst = constructor.newInstance(); 
    inst.showFields(); 
    return inst; 
} 

(또는 생성자 조금도).

+2

'make'는 여전히 자식이 아닌 부모의 인스턴스를 생성합니다. – assylias

+1

@assylias 좋은 지적.추가 인스턴스 코드 –

+0

그것이 의미가 있지만, 나는 그것이 문제라고 생각하지 않습니다. 부모에 대한 속성은 이미 발견되었으며, 자식 속성은 아직 초기화되지 않았습니다. 수정 : 귀하의 편집에 대해, 나는'클래스 타입'무엇인지 모르겠다, 그걸 살펴보고 돌아와 – Mark