使用 Java 反射访问嵌套字段
Access Nested Field using Java Reflection
假设我有几个class这种风格的:
public class A {
public B element;
}
public class B {
public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
}
我想遍历所有包含的子classes(不是继承的)并获得嵌套对象树中所有字段的列表。但是,当我使用这样的反射代码时:
Field[] myFields = providedObject.getClass().getDeclaredFields();
for (Field myField : myFields) {
// do something here?? to access the sub-fields of the class
// if I print out myField.getName(), I get the element of class A, but I also want to access the anotherElement of class B (without hard-coding the name 'anotherElement', I want a full traversal of all nested fields)
}
在 'do something here' 这一步,我想访问 myField 的子字段,但我在字段 api 中看不到任何东西可以直接让我这样做。我试过:
myField.getDeclaringClass().getDeclaredFields() -> 这似乎 return 我们已经看到的相同元素,而不是子元素
和
myField.getClass().getDeclaredFields() -> 这似乎 return 'Field' class 的字段而不是我的 class A 或B
那么我如何从反射中访问嵌套字段 api?
谢谢。
我添加了以下语句来退出递归方法。你可以随心所欲地改变它。
if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
return;
}
主要思想是您需要通过键入以下行将字段转换为 class。
Class<?> fieldClass = myField.getType();
public class Main {
public static void main(String[] args) {
printFields(A.class);
}
public static void printFields(Class<?> clazz) {
if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
return;
}
Field[] myFields = clazz.getDeclaredFields();
for (Field myField : myFields) {
System.out.println(clazz.getSimpleName() + "->" + myField.getType().getSimpleName() + ":" + myField.getName());
Class<?> fieldClass = myField.getType();
printField(fieldClass);
}
}
public static class A {
public B element;
}
public static class B {
public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
}
public static class C {
public Integer a;
}
}
只是递归了一点:
public static void traverseDepthFirst(Object obj) { // May need throws/catch!
if (obj == null) {
// ... do something for null ...
return;
}
// ... perhaps do something different for arrays, primitives, String, etc.
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
// ... pre-traversal code ...
traverseDepthFirst(field.get(obj));
// ... post-traversal code ...
}
}
编辑: 那只会考虑叶子class。包括超级 classes.
public static void traverseDepthFirst(Object obj) { // May need throws/catch!
if (obj == null) {
// ... do something for null ...
return;
}
// ... perhaps do something different for arrays, primitives, String, etc.
for (
Class<?> clazz = obj.getClass();
clazz != null;
clazz = clazz.getSuperclass()
) {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
// ... pre-traversal code ...
traverseDepthFirst(field.get(obj));
// ... post-traversal code ...
}
}
}
假设我有几个class这种风格的:
public class A {
public B element;
}
public class B {
public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
}
我想遍历所有包含的子classes(不是继承的)并获得嵌套对象树中所有字段的列表。但是,当我使用这样的反射代码时:
Field[] myFields = providedObject.getClass().getDeclaredFields();
for (Field myField : myFields) {
// do something here?? to access the sub-fields of the class
// if I print out myField.getName(), I get the element of class A, but I also want to access the anotherElement of class B (without hard-coding the name 'anotherElement', I want a full traversal of all nested fields)
}
在 'do something here' 这一步,我想访问 myField 的子字段,但我在字段 api 中看不到任何东西可以直接让我这样做。我试过:
myField.getDeclaringClass().getDeclaredFields() -> 这似乎 return 我们已经看到的相同元素,而不是子元素
和
myField.getClass().getDeclaredFields() -> 这似乎 return 'Field' class 的字段而不是我的 class A 或B
那么我如何从反射中访问嵌套字段 api?
谢谢。
我添加了以下语句来退出递归方法。你可以随心所欲地改变它。
if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
return;
}
主要思想是您需要通过键入以下行将字段转换为 class。
Class<?> fieldClass = myField.getType();
public class Main {
public static void main(String[] args) {
printFields(A.class);
}
public static void printFields(Class<?> clazz) {
if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
return;
}
Field[] myFields = clazz.getDeclaredFields();
for (Field myField : myFields) {
System.out.println(clazz.getSimpleName() + "->" + myField.getType().getSimpleName() + ":" + myField.getName());
Class<?> fieldClass = myField.getType();
printField(fieldClass);
}
}
public static class A {
public B element;
}
public static class B {
public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
}
public static class C {
public Integer a;
}
}
只是递归了一点:
public static void traverseDepthFirst(Object obj) { // May need throws/catch!
if (obj == null) {
// ... do something for null ...
return;
}
// ... perhaps do something different for arrays, primitives, String, etc.
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
// ... pre-traversal code ...
traverseDepthFirst(field.get(obj));
// ... post-traversal code ...
}
}
编辑: 那只会考虑叶子class。包括超级 classes.
public static void traverseDepthFirst(Object obj) { // May need throws/catch!
if (obj == null) {
// ... do something for null ...
return;
}
// ... perhaps do something different for arrays, primitives, String, etc.
for (
Class<?> clazz = obj.getClass();
clazz != null;
clazz = clazz.getSuperclass()
) {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
// ... pre-traversal code ...
traverseDepthFirst(field.get(obj));
// ... post-traversal code ...
}
}
}