在具有继承的构造函数中进行反射 (Java)
Reflection in constructor with inheritance (Java)
我无法在 class 构造函数中使用继承进行反射。具体来说,我想获取所有属性值。
这是一个无法正常工作的简单实现的演示:
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
不是 return subclass 的正确类型。 (所以问题是new SolParent();
)。
解决这个问题的最佳方法是什么? 我需要所有子classes 来执行showFields
,但我不能依赖他们明确地执行它。
您的 showFields 方法需要遍历 class 层次结构,如下所示:
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();
}
}
注意我用的是Class.getDeclaredFields()
, not Class.getFields()
,因为后者只处理public个字段
这就是您如何以通用方式构建 classes:
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;
}
请注意,这仅在您的 SolParent
子类型具有 public 无参数构造函数(或根本没有构造函数)时才有效。
我无法在 class 构造函数中使用继承进行反射。具体来说,我想获取所有属性值。
这是一个无法正常工作的简单实现的演示:
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
不是 return subclass 的正确类型。 (所以问题是new SolParent();
)。
解决这个问题的最佳方法是什么? 我需要所有子classes 来执行showFields
,但我不能依赖他们明确地执行它。
您的 showFields 方法需要遍历 class 层次结构,如下所示:
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();
}
}
注意我用的是Class.getDeclaredFields()
, not Class.getFields()
,因为后者只处理public个字段
这就是您如何以通用方式构建 classes:
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;
}
请注意,这仅在您的 SolParent
子类型具有 public 无参数构造函数(或根本没有构造函数)时才有效。