継承を使用してクラスコンストラクタでリフレクションを作成する際に問題が発生しました。具体的には、すべての属性値を取得したいと考えています。ここで継承を持つコンストラクタでのリフレクション(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
がゼロであることが表示されます:
public int Child.childVar: 0
public int Parent.parentVar: 888888
それはまだ初期化されていませんだから。
だから私は、私が直接コンストラクタを使用しないようにする必要がありますね、ではなく、コンストラクタが完了してみましょうとその後、使用showFields
:
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
が戻らないので、それが動作しません。サブクラスの正しい型。 (だから問題は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();
}
}
注:
2番目の例では、なぜ 'make'メソッドを実装するのですか?なぜ新しいSolChild()を使わないのですか?showFields(); – ToYonos
コンストラクタからそのようなメソッドを呼び出さないでください。それらは初期化に寄与しないため、コンストラクタに属しません。 –
@ ToYonosそれでは、私のクラスを使っている人がそれを忘れるかもしれないので – Mark