反射泛型获取字段值

Ido*_*ash 125 java reflection

我试图通过反射接收字段值.问题是我不知道字段类型,必须在获取值时决定它.

此代码导致此异常:

无法将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);
Run Code Online (Sandbox Code Playgroud)

我试图施放,但我得到编译错误:

field.get((targetType)objectValue)
Run Code Online (Sandbox Code Playgroud)

要么

targetType objectValue = targetType.newInstance();
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

Mar*_*ius 133

像之前的回答一样,您应该使用:

Object value = field.get(objectInstance);
Run Code Online (Sandbox Code Playgroud)

另一种有时候首选的方法是动态调用getter.示例代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

还要注意,当您的类继承自另一个类时,您需要递归地确定Field.例如,获取给定类的所有字段;

    for (Class<?> c = someClass; c != null; c = c.getSuperclass())
    {
        Field[] fields = c.getDeclaredFields();
        for (Field classField : fields)
        {
            result.add(classField);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 您需要自己遍历超类似乎并不完全正确。c.getFields() 或 c.getField() 将自动搜索每个实现接口上的字段,并递归地遍历所有超类。所以只要从 getDeclaredX 切换到 getX 就足够了。 (2认同)
  • 的确,使用getFields()例程可以获取所有超类和接口的字段,但只能获取公共的类和接口的字段。通常,将字段设置为私有/受保护,并通过getter / setter公开。 (2认同)
  • @Marius,我可以知道`BaseValidationObject` 是什么包吗? (2认同)
  • 第一个片段中的“object”未定义,读者无法理解如何使用它。 (2认同)

Dmi*_*kiy 114

您应该传递一个对象获取字段的方法,所以

  Field field = object.getClass().getDeclaredField(fieldName);    
  field.setAccessible(true);
  Object value = field.get(object);
Run Code Online (Sandbox Code Playgroud)

  • @serup否,Field对象来自Class对象,它与您的实际实例没有任何关系.(````object.getClass()```将返回此Class对象) (16认同)
  • 你知道为什么对象必须在field.get(object)中使用的原因 - 字段本身来自那个对象,为什么它又需要它呢? (6认同)
  • 代码片段中的“object”未定义,因此读者无法理解如何使用它。 (6认同)
  • 投反对票。field.get(object) 未澄清。需要在“object”中传递什么? (4认同)

sil*_*urf 17

我使用我的首选项类的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();
}
Run Code Online (Sandbox Code Playgroud)

我希望它会帮助某人,因为我也有搜索过.


Cos*_*atu 10

虽然我不太清楚你想要实现什么,但我发现你的代码中有一个明显的错误: Field.get()期望包含该字段的对象作为参数,而不是该字段的某些(可能的)值.所以你应该有field.get(object).

由于您似乎在寻找字段值,因此可以将其作为:

Object objectValue = field.get(object);
Run Code Online (Sandbox Code Playgroud)

无需实例化字段类型并创建一些空/默认值; 或许我错过了一些东西.

  • `object` 没有定义,读者无法理解如何应用答案。 (6认同)

Rah*_*rma 10

 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();
 }
Run Code Online (Sandbox Code Playgroud)

  • 请在您的代码中添加说明。 (2认同)

小智 7

    ` 
//Here is the example I used for get the field name also the field value
//Hope This will help to someone
TestModel model = new TestModel ("MyDate", "MyTime", "OUT");
//Get All the fields of the class
 Field[] fields = model.getClass().getDeclaredFields();
//If the field is private make the field to accessible true
fields[0].setAccessible(true);
//Get the field name
  System.out.println(fields[0].getName());
//Get the field value
System.out.println(fields[0].get(model));
`
Run Code Online (Sandbox Code Playgroud)