使用反射使用超类获取子类字段



我有一个如下的类。

public class Emp{
 private String name;
 private String age;
 //setters and getters
}

下面再上一节课。

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

无论如何要得到一个子类的字段使用超类使用java反射?我需要使用Emp实例获取学生字段。

我们可以像下面这样获得超类字段:

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

同样我可以得到子类字段使用超类?

有可能吗?

谢谢!

我可能误解了你的问题。你想做下面的事情吗?
 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 = ....

那么不,这是不可能的,我怀疑你的java对象模型的内部模型要么是不完整的,要么是有缺陷的。

理论上有一种非常复杂和昂贵的方法,即检索所有加载的类并检查哪些类派生自Emp并包含该字段。如果所需的类还没有加载,这可能也没有帮助。

不直接,你必须写一个辅助方法。

将一个类和字段名(可能还有类型)作为参数,然后在给定的类中查找该字段。如果找不到,就取这个类的父类,从头开始重复。您可以这样做,直到找到该字段,或者getSuperClass()返回null(意味着您到达了继承树的根)。

这个例子演示了如何在对象上调用find和调用指定的方法。您可以轻松地提取和调整字段的逻辑。
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;
}

这是你想要的吗?但是要注意不要使用field. setaccessible .

父类

:

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();
       }
}

这是最终的解决方案!

    @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]

相关内容

  • 没有找到相关文章

最新更新