web-dev-qa-db-ja.com

リフレクションジェネリック取得フィールド値

リフレクションを介してフィールド値を受け取るようにしています。問題は、フィールドの種類がわからないため、値を取得しながら決定する必要があることです。

このコードは、次の例外があります。

Java.lang.Stringフィールドcom .... fieldNameをJava.lang.Stringに設定できません

Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);

Class<?> targetType = field.getType();
Object objectValue = targetType.newInstance();

Object value = field.get(objectValue);

キャストしようとしましたが、コンパイルエラーが発生します。

field.get((targetType)objectValue)

または

targetType objectValue = targetType.newInstance();

これどうやってするの?

114
Ido Barash

前に答えたように、あなたは使うべきです:

Object value = field.get(objectInstance);

時々好まれるもう一つの方法は、動的にゲッターを呼び出すことです。コード例:

public static Object runGetter(Field field, BaseValidationObject o)
{
    // MZ: Find the correct method
    for (Method method : o.getMethods())
    {
        if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3)))
        {
            if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
            {
                // MZ: Method found, run it
                try
                {
                    return method.invoke(o);
                }
                catch (IllegalAccessException e)
                {
                    Logger.fatal("Could not determine method: " + method.getName());
                }
                catch (InvocationTargetException e)
                {
                    Logger.fatal("Could not determine method: " + method.getName());
                }

            }
        }
    }


    return null;
}

また、自分のクラスが他のクラスから継承するときは、再帰的にFieldを決定する必要があることにも注意してください。たとえば、特定のクラスのすべてのフィールドを取得するためなどです。

    for (Class<?> c = someClass; c != null; c = c.getSuperclass())
    {
        Field[] fields = c.getDeclaredFields();
        for (Field classField : fields)
        {
            result.add(classField);
        }
    }
123
Marius

fieldgetメソッドにobjectを渡すべきです。

  Field field = object.getClass().getDeclaredField(fieldName);    
  field.setAccessible(true);
  Object value = field.get(object);
100

私は自分の設定クラスのtoString()実装のリフレクションを使ってクラスのメンバーと値を確認します(簡単で迅速なデバッグ)。

私が使っている単純化されたコード:

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();

    Class<?> thisClass = null;
    try {
        thisClass = Class.forName(this.getClass().getName());

        Field[] aClassFields = thisClass.getDeclaredFields();
        sb.append(this.getClass().getSimpleName() + " [ ");
        for(Field f : aClassFields){
            String fName = f.getName();
            sb.append("(" + f.getType() + ") " + fName + " = " + f.get(this) + ", ");
        }
        sb.append("]");
    } catch (Exception e) {
        e.printStackTrace();
    }

    return sb.toString();
}

私も検索したので、それが誰かに役立つことを願っています。

16
silversmurf
 Integer typeValue = 0;
 try {
     Class<Types> types = Types.class;
     Java.lang.reflect.Field field = types.getDeclaredField("Type");
     field.setAccessible(true);
     Object value = field.get(types);
     typeValue = (Integer) value;
 } catch (Exception e) {
     e.printStackTrace();
 }
10
Rahul sharma

あなたが何を達成しようとしているのかは私には明らかではありませんが、私はあなたのコードに明らかなエラーを見つけました:Field.get()は引数としてフィールドを含むオブジェクトを期待します。だからあなたはfield.get(object)を持つべきです。

あなたはフィールドの値を探しているように見えるので、あなたはそれを次のように得ることができます。

Object objectValue = field.get(object);

フィールドタイプをインスタンス化して空の値またはデフォルト値を作成する必要はありません。または私が逃した何かがあるかもしれません。

7
Costi Ciudatu

あなたは間違った引数でgetを呼んでいます。

そのはず:

Object value = field.get(object);
4
Seba