2

重複の可能性:
Java でのリフレクションを介したプライベート継承フィールドへのアクセス

こんにちは、Java リフレクションの初期値に問題があります。

私は簡単なクラスを持っています

 public class A extends B {
     private String name;
 }

  public class B {
     private String superName;   
  }

また、私は単純な機能を持っています:

   public void createRandom(Class<T> clazz , List<String> classFields){


    try {
        T object = clazz.newInstance();
        for(String s : classFields){
            clazz.getDeclaredField(s);
        }

    } catch(Exception e){

    }

   }

私の関数は他のことをしますが、エラーがあるため問題があります:

java.lang.NoSuchFieldException: superName

リフレクションを使用してすべてのクラス フィールドとスーパー クラスのフィールドを設定するにはどうすればよいですか??

私はすべてのクラス フィールド (継承も) を取得し、関数を使用していますfield.set(Object obj, Object value)が、この方法では継承されたクラス フィールドを設定できません:/

Spring ReflectionUtils.doWithfield を使用しているすべてのクラス フィールドを取得するのに問題はありません。すべてのフィールド名を に保存したList<String> classFieldので、すべての clazz フィールドも継承されていることがわかりました。しかし、私の問題は、すべての clazz フィールドに値を設定する方法です。

4

4 に答える 4

7

推測する必要がある場合は、クラスAでこのメソッドを呼び出しており、クラスBで宣言されている基になるフィールドを次のように表示できることを期待しています。

A.class.getDeclaredField("superName");

これは当てはまらず、例外(java.lang.NoSuchFieldException)をスローします。リフレクションは、フィールドまたはメソッドを見つけるためにスーパークラスをチェックしません。したがって、クラスAは定義されていないためsuperName、そのようなリフレクションを使用しても検出されません。ただし、コードを変更してnull、スーパークラスとして到達するまですべてのスーパークラスをチェックするようにすることができます。その時点でまだ見つからない場合は、間違いなく存在しません。

次に例を示します。

public static Field findUnderlying(Class<?> clazz, String fieldName) {
    Class<?> current = clazz;
    do {
       try {
           return current.getDeclaredField(fieldName);
       } catch(Exception e) {}
    } while((current = current.getSuperclass()) != null);
    return null;
}

呼び出しの例を次に示します。findUnderlying(A.class, "superName"); 最初にフィールドのクラスAをチェックします。Aにはそれがないので、その間、そのスーパークラスであるBに移動します(nullではないので続行します)。Bはそれを持っているので、フィールドを返します。Bにそれがない場合は、Objectをチェックし、Objectにスーパークラスがないためnullを返します。

于 2012-09-18T21:36:53.600 に答える
6

以下を使用できます。

clazz.getSuperclass().getDeclaredField(s);

代わりに (またはいくつかの try-catch に加えて):

clazz.getDeclaredField(s);

編集:

スーパークラスの値を設定するには、次を使用します。

Field f = clazz.getSuperclass().getDeclaredField(s);
f.setAccessible(true); // Especially necessary if the field is not public
f.set(yourObject, theValue);
于 2012-09-18T21:40:57.803 に答える
1

Class.getSuperclass()を使用してスーパークラスを取得します。次に、スーパークラスを使用して、そのフィールドを取得できます。

于 2012-09-18T21:39:48.333 に答える
-1

AがBから拡張されている場合でも、Aのインスタンスでは機能しません。これは、サブクラスでプライベートメンバーにアクセスできないためです。superNameのアクセスをprotectedに変更してみてください。それが機能するかどうか...

于 2012-09-18T21:36:04.770 に答える