Java 如何使用反射获取嵌套类属性的值?
目前我在is中有几个嵌套类,如:Java 如何使用反射获取嵌套类属性的值?,java,reflection,Java,Reflection,目前我在is中有几个嵌套类,如: public class Foo { private Bar bar; //getter & setter public class Bar { private Abc abc; //getter & setter public class Abc { @RequiredParam private String property; //getter &
public class Foo {
private Bar bar;
//getter & setter
public class Bar {
private Abc abc;
//getter & setter
public class Abc {
@RequiredParam
private String property;
//getter & setter
}
}
}
我试图得到的领域的价值,但我有一个艰难的时间如何实现这一点
到目前为止,我已经:
public static boolean isValid(Object paramClazz) throws Exception {
List<Class> classes = new ArrayList<>();
getClasses(classes, paramClazz.getClass());
for (Class clazz : classes) {
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(RequiredParam.class)) {
field.setAccessible(true);
//how to get the value? field.get(paramClazz) doesn't work
}
}
}
return true;
}
private static void getClasses(List<Class> classes, Class<?> clazz) {
if (clazz.getDeclaredClasses().length > 0) {
for (Class<?> c : clazz.getDeclaredClasses()) {
getClasses(classes, c);
}
}
classes.add(clazz);
}
我的目标是能够检查用@RequiredParam注释的字段是否不为null,因此我有一个方法isValid,它将接收一个对象,应该能够检查所有字段,甚至是嵌套类中的字段,并查看是否缺少任何字段
问题是当我尝试调用field.get时,我不知道应该将哪个对象传递给这个方法。传递最高级别的对象不会起作用,因为我需要以某种方式只将Abc对象传递给该方法
考虑到我的类中可以有更多或更少的嵌套级别,如何获取要传递给field.get调用的正确对象?这是一个示例代码,它递归扫描对象的所有字段,直到找到所有带注释字段的值:
public static Collection<Object> getAnnotatedValues(final Object root) throws ReflectiveOperationException {
return getAnnotatedValues(root, new HashSet<>());
}
private static Collection<Object> getAnnotatedValues(final Object root, final Set<Object> inspected)
throws ReflectiveOperationException {
final List<Object> annotatedValues = new ArrayList<>();
if (inspected.contains(root)) { // Prevents stack overflow.
return Collections.EMPTY_LIST;
}
inspected.add(root);
for (final Field field : gatherFields(root.getClass())) {
field.setAccessible(true);
final Object currentValue = field.get(root);
field.setAccessible(false);
if (field.isAnnotationPresent(RequiredParam.class)) {
// Found required value, search finished:
annotatedValues.add(currentValue);
if (currentValue != null) {
inspected.add(currentValue);
}
} else if (currentValue != null) {
// Searching for annotated fields in nested classes:
annotatedValues.addAll(getAnnotatedValues(currentValue, inspected));
}
}
return annotatedValues;
}
private static Iterable<Field> gatherFields(Class<?> fromClass) {
// Finds ALL fields, even the ones from super classes.
final List<Field> fields = new ArrayList<>();
while (fromClass != null) {
fields.addAll(Arrays.asList(fromClass.getDeclaredFields()));
fromClass = fromClass.getSuperclass();
}
return fields;
}
…getAnnotatedValuesnew Foo返回包含结果的集合。。您可以轻松地修改方法以满足您的需要,例如,在找到第一个有效的带注释字段时立即返回true,或者如果集合为空/包含null,则只返回false。如果您可以澄清代码,这将非常有帮助。一定要告诉我们你到底想得到什么。我没有看到名为field的对象或名为gett的方法。规则与顶级类的规则相同:您需要一个类的实例,您试图读取该类的非静态字段值。也就是说,您需要一个Foo.Bar.Abc的现有实例。@VGR问题是我如何浏览顶级类实例并以编程方式获取所需的特定实例?除非您计划自己实例化内部类,否则不需要这样做。很可能这个实例是在别处创建的,就像其他Java对象一样;和其他Java对象一样,这个程序可以有任意数量的引用。真是太棒了。比我想做的要优雅得多。我试图调整它以返回字段本身,但不确定从哪里开始。有什么建议吗?我现在都不记得写过了,但是将annotatedValues.addcurrentValue更改为annotatedValues.addfield可能是一个好的开始。您可能需要同时存储对字段和根的引用,但是,一个小的数据类可能是一个好主意。如果你把你想要达到的目标和你已经尝试过的作为一个单独的问题发布出来,我会尽我所能找到时间和答案。
public class Foo {
private final Bar bar = new Bar();
public class Bar {
private final Abc abc = new Abc();
public class Abc {
@RequiredParam private final String property = "Result.";
}
}
@Retention(RetentionPolicy.RUNTIME)
public static @interface RequiredParam {}
}