web-dev-qa-db-ja.com

Javaリフレクトをスーパークラスのスポットフィールドに反映させる方法は?実際のクラスだけではありませんか?

最近、スキーマを少し変更して、クラスがスーパークラスから継承するようにしました。問題は、Java Reflectを使用して、監査ログを生成する比較メソッドが、のフィールドのみをループしていることです。スーパークラスではなく子クラスにすべてのFIELDSを取得する方法はありますか?それともスーパークラスにキャストする必要がありますか.....?

以下に私の方法を示します。

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

このthis.getClass().getSuperClass()メソッドがnullを返すまでgetSuperClass()を使用して、親フィールドを取得できます。

したがって、コードを因数分解するのが最善です。 Fieldのリストをパラメーターとして受け取り、その中で論理部分を実行する1つのメソッドと、while(superClass != null)ループを介してフィールドを検索するmainメソッドを実装します。

34
sp00m

遅いですが、それは素晴らしい解決策なので、私は私の提案を追加しています。

SpringフレームワークはNiceUtilクラスを提供します_org.springframework.util.ReflectionUtils_このクラスには、使用できるいくつかのメソッドがあります。 objectClassとsuperClassesから属性のFieldインスタンスを取得するには、ReflectionUtils.findField(clazz, fieldName);を使用しました

utilの良いところは、例外をスローしないことです。代わりに、無効なものに対してnullを返すため、適切に処理できます。

10
mds404

Apache Commons Langは、@ sp00mのアルゴリズムの実装であるメソッド FieldUtils.getAllFields() を提供します。

2
Václav Kužel