java Java反射:查找子类的字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2172263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:50:33  来源:igfitidea点击:

Java reflection: Find fields of a subclass

javareflection

提问by roufamatic

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. Within that method in "A", I want to use reflection to find protected fields of the object that are defined in class "B". (So these are fields that "C" and "B" can see, but not "A".)

执行时,“C”调用“A”的方法之一。在“A”中的该方法中,我想使用反射来查找在类“B”中定义的对象的受保护字段。(所以这些是“C”和“B”可以看到的字段,而不是“A”。)

How would I do this with Java reflection? And how can I future-proof it in case I add something between A & B or B & C?

我将如何使用 Java 反射来做到这一点?如果我在 A 和 B 或 B 和 C 之间添加一些东西,我怎样才能使它面向未来?

回答by Michael Borgwardt

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 areyou trying to do that you think requires such reflection shenanigans?

但是,您的计划听起来像是对继承概念的严重违反。面向未来的最好方法是完全避免这种事情。什么你想干什么,你认为需要这样的反思有心计?

回答by Bozho

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()(while getSuperclass() != Object.class)的递归调用,从而收集所有超类的所有字段。

回答by aperkins

As far as I know, there is no way to know about your "child classes" in Java reflectively. Wouldn't a better solution be to create an abstract method on A that B would have to implement, and call that instead?

据我所知,没有办法反射性地了解 Java 中的“子类”。不是更好的解决方案是在 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 cando 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. 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. 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.

然而,这只有在 C 总是直接从 B 继承时才有效。反射就其本质而言,是棘手和特定的。我必须在我参与的项目中做很多事情(不要问,相信我,你不想知道),我尽可能避免这样做。除非 A 有充分的理由需要受保护的字段并且它正在发现有关它们的信息,否则您可能希望使用抽象方法。我还认为您可能可以使用抽象方法解决另一个问题,但这可能会有点困难。

回答by Denis A

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