简体   繁体   English

Java反射:查找子类的字段

[英]Java reflection: Find fields of a subclass

I have a class hierarchy like so: (=> means "is a subclass of")我有一个这样的类层次结构:(=> 表示“是”的子类)

anonymous instance class => abstract class => generic abstract class

or more succinctly:或更简洁地说:

C => B => A

When executing, "C" calls one of "A"'s methods.执行时,“C”调用“A”的方法之一。 Within that method in "A", I want to use reflection to find protected fields of the object that are defined in class "B".在“A”中的该方法中,我想使用反射来查找在类“B”中定义的对象的受保护字段。 (So these are fields that "C" and "B" can see, but not "A".) (所以这些是“C”和“B”可以看到的字段,但“A”看不到。)

How would I do this with Java reflection?我将如何使用 Java 反射来做到这一点? And how can I future-proof it in case I add something between A & B or B & C?如果我在 A 和 B 或 B 和 C 之间添加一些东西,我如何才能使它面向未来?

You have to use getDeclaredFields() repeatedly on each class in the inheritance hierarchy of your object's class (via getSuperclass() ).您必须在对象类的继承层次结构中的每个类上重复使用getDeclaredFields() (通过getSuperclass() )。

However, what you are planning sounds like a nasty violation of the concept of inheritance.但是,您的计划听起来像是对继承概念的严重违反。 The best way of future-proofing would be to avoid this kind of thing entirely.面向未来的最好方法是完全避免这种事情。 What are you trying to do that you think requires such reflection shenanigans?什么你想这样做,你觉得需要这样有心计反思?

Field[] fields = getClass().getSuperclass().getDeclaredFields();

And then iterate those fields and get the ones you want.然后迭代这些字段并获得您想要的字段。

In case your hierarchy grows, you can transform the above to a recursive calls to getSuperclass() (while getSuperclass() != Object.class ), thus collecting all fields of all superclasses.如果您的层次结构增长,您可以将上述转换为对getSuperclass()的递归调用(而getSuperclass() != Object.class ),从而收集所有超类的所有字段。

As far as I know, there is no way to know about your "child classes" in Java reflectively.据我所知,没有办法反射性地了解 Java 中的“子类”。 Wouldn't a better solution be to create an abstract method on A that B would have to implement, and call that instead?不是更好的解决方案是在 A 上创建一个 B 必须实现的抽象方法,然后调用它吗?

public class A {
   //other stuff here
   protected void abstract mySubMethod();
   //other stuff here
}

Edit: If I have misunderstood your question, and you actually want to know about parent classes, then yes: getDeclaredFields() is the correct reflective method to use, as mentioned by other posters.编辑:如果我误解了您的问题,而您实际上想了解父类,那么是的:getDeclaredFields() 是正确的反射方法,如其他海报所述。

Additional Edit: I hate to keep modifying this answer, but... In general, if you are attempting to give access to a parent class, the "correct" and "future proof" way to do this is to create abstract methods that are getters or setters (or even more complex, if necessary) and then have the children honor those or not, and respond as appropriate.附加编辑:我讨厌不断修改这个答案,但是......一般来说,如果您试图访问父类,那么“正确”和“面向未来”的方法是创建抽象方法,这些方法是getter 或 setter(或什至更复杂,如果有必要),然后让孩子尊重或不尊重它们,并做出适当的回应。

That being said, you can do something like the others have said:话虽如此,您可以像其他人所说的那样做:

getClass().getParentClass().getDeclaredFields()

However, that would only work if C is always directly inherited from B. Reflections is, by it's very nature, tricky and specific.然而,这只有在 C 总是直接从 B 继承时才有效。反射就其本质而言,是棘手和特定的。 I have to do a LOT of it on a project I am on (don't ask, trust me, you DON'T want to know), and I avoid it whenever possible.我必须在我参与的项目中做很多事情(不要问,相信我,你不想知道),我尽可能避免这样做。 Unless there is a good reason for A to need the protected fields and it is discovering information about them, then you would likely want to use an abstract method.除非 A 有充分的理由需要受保护的字段并且它正在发现有关它们的信息,否则您可能希望使用抽象方法。 I would also submit that it is likely that you can solve the other problem with an abstract method, however it might be a little bit harder.我还认为您可能可以使用抽象方法解决另一个问题,但这可能会有点困难。

Example of recursive method for java 8+ java 8+的递归方法示例

static final Field[] getDeclaredFields(Class clazz) {
    final Field[] fields = clazz.getDeclaredFields();

    if ( clazz.getSuperclass() != Object.class ) {
        final Field[] pFields = getDeclaredFields(clazz.getSuperclass());
        final Field[] allFields = new Field[fields.length + pFields.length];
        Arrays.setAll(allFields, i -> (i < pFields.length ? pFields[i] : fields[i - pFields.length]));
        return allFields;
    } else
        return fields;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM