簡體   English   中英

使用反射使用超類獲取子類字段?

[英]Getting sub class fields using super class using reflection?

我有一個課程如下。

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實例獲取Student字段。

我們可以得到如下的超類字段:

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

這是最終的解決方案!

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM