如何让Java反射找到超类中的字段?而不仅仅是实际类

28

最近我对架构进行了一些更改,使我的类继承自一个超类。问题是我的比较方法生成审计日志时,使用Java reflect只遍历了子类的字段,而没有遍历超类的字段。有没有办法获取所有的字段?还是需要将其转换为超类......?

下面是我的方法:

public static <T> String GenerateChangeLogForEntity(T old, T updated) {
        String text = "";
        try {
            Field[] fields = old.getClass().getDeclaredFields();
            if(fields != null) {
                BaseController.getLogger().info("Z1 num fields:"+fields.length);
                for (Field field : fields) {
                    if(field.isAnnotationPresent(Column.class)) {
                        String fieldName = field.getName();
                        BaseController.getLogger().info(field.getName());
                        if(field.isAnnotationPresent(Variation.class)) {
                            Variation v = field.getAnnotation(Variation.class);
                            fieldName = v.friendlyName();
                        }
                        field.setAccessible(true);
                        if(field.get(old) != null && field.get(updated) != null) {
                            if(!(field.get(old)).equals(field.get(updated))) {
                                text += "<p><span class=\"field-name\">"+fieldName+"</span> changed from: <strong>"+GetFriendlyFieldValueForChangeLog(field.get(old))+"</strong>  to: <strong>"+GetFriendlyFieldValueForChangeLog(field.get(updated)) + "</strong></p>";
                            }
                        }
                        if(field.get(old) == null && field.get(updated) != null) {
                            text += "<p><span class=\"field-name\">"+fieldName+"</span> changed from: <strong>empty</strong> to: <strong>"+GetFriendlyFieldValueForChangeLog(field.get(updated)) + "</strong></p>";
                        }
                        if(field.get(old) != null && field.get(updated) == null) {
                            text += "<p><span class=\"field-name\">"+fieldName+"</span> changed from: <strong>"+GetFriendlyFieldValueForChangeLog(field.get(updated))+"</strong> to <strong>empty</strong>" + "</p>";
                        }
                        field.setAccessible(false);
                    }
                }
            }
        } catch(IllegalAccessException e) {}
        return text;
    }

注意:在多线程环境中,您可能不应该设置 field.setAccessible(false) 以防止竞态条件... - Lukas Eder
1
你的意思是:instance.getClass().getSuperCLass().getDeclaredFields() - Sam
谢谢MJM,谢谢大家,没错,这样做真是轻而易举! :) - williamsandonz
3个回答

43

您可以使用this.getClass().getSuperClass()方法获取父类字段,直到此getSuperClass()方法返回null。

因此,最好的方法是将代码因式分解。实现一个以Field列表为参数的方法,并在其中完成逻辑部分,主方法通过while(superClass != null)循环搜索字段。


2
注意getFields()方法,在我的情况下它对于超类不起作用。我只能成功地使用getDeclaredFields()方法。 - Gonçalo

18

虽然有点晚,但我还是想提供一个建议,因为它是一个不错的解决方案。

Spring框架提供了一个很好的实用类org.springframework.util.ReflectionUtils,这个类有几个我们可以使用的方法。 要从objectClass和superClasses中获取属性的Field实例,我使用了ReflectionUtils.findField(clazz, fieldName);

工具的好处是它不会抛出异常。相反,对于无效的参数它会返回null,因此您可以优雅地进行处理。


9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接