简体   繁体   English

反射泛型获取字段值

[英]Reflection generic get field value

I am trying to obtain a field's value via reflection.我正在尝试通过反射获取字段的值。 The problem is I don't know the field's type and have to decide it while getting the value.问题是我不知道该字段的类型,并且必须在获取值时决定它。

This code results with this exception:此代码导致此异常:

Can not set java.lang.String field com....fieldName to java.lang.String无法将 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);

I tried to cast, but I get compilation errors:我尝试强制转换,但出现编译错误:

field.get((targetType)objectValue)

or或者

targetType objectValue = targetType.newInstance();

How can I do this?我怎样才能做到这一点?

Like answered before, you should use:就像之前回答的那样,您应该使用:

Object value = field.get(objectInstance);

Another way, which is sometimes prefered, is calling the getter dynamically.另一种有时更受欢迎的方法是动态调用 getter。 example code:示例代码:

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

Also be aware that when your class inherits from another class, you need to recursively determine the Field.另请注意,当您的类继承自另一个类时,您需要递归确定 Field。 for instance, to fetch all Fields of a given class;例如,获取给定类的所有字段;

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

You should pass the object to get method of the field , so您应该将对象传递给字段get方法,所以

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

I use the reflections in the toString() implementation of my preference class to see the class members and values (simple and quick debugging).我在我的首选项类的 toString() 实现中使用反射来查看类成员和值(简单快速的调试)。

The simplified code I'm using:我正在使用的简化代码:

@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();
}

I hope that it will help someone, because I also have searched.我希望它会对某人有所帮助,因为我也搜索过。

Although it's not really clear to me what you're trying to achieve, I spotted an obvious error in your code: Field.get() expects the object which contains the field as argument, not some (possible) value of that field.尽管我不太清楚您要实现什么,但我在您的代码中发现了一个明显的错误: Field.get()需要包含该字段作为参数的对象,而不是该字段的某些(可能)值。 So you should have field.get(object) .所以你应该有field.get(object)

Since you appear to be looking for the field value, you can obtain that as:由于您似乎正在寻找字段值,因此您可以通过以下方式获得:

Object objectValue = field.get(object);

No need to instantiate the field type and create some empty/default value;无需实例化字段类型并创建一些空/默认值; or maybe there's something I missed.或者也许我错过了一些东西。

 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();
 }
    ` 
//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));
`

I post my solution in Kotlin, but it can work with java objects as well.我在 Kotlin 中发布了我的解决方案,但它也可以与 java 对象一起使用。 I create a function extension so any object can use this function.我创建了一个函数扩展,因此任何对象都可以使用这个函数。

fun Any.iterateOverComponents() {

val fields = this.javaClass.declaredFields

fields.forEachIndexed { i, field ->

    fields[i].isAccessible = true
    // get value of the fields
    val value = fields[i].get(this)

    // print result
    Log.w("Msg", "Value of Field "
            + fields[i].name
            + " is " + value)
}}

Take a look at this webpage: https://www.geeksforgeeks.org/field-get-method-in-java-with-examples/看看这个网页: https ://www.geeksforgeeks.org/field-get-method-in-java-with-examples/

Was able to access private fields in a class using following method能够使用以下方法访问类中的私有字段

 Beneficiary ben = new Beneficiary();//class with multiple fields
 ben.setName("Ashok");//is set by a setter
                
 //then to get that value following was the code which worked for me
 Field[] fields = ben.getClass().getDeclaredFields();
    
 for(Field field: fields) {
   field.setAccessible(true);//to access private fields
   System.out.println(field.get(ben));//to get value
   //assign value for the same field.set(ben, "Y");//to set value
 }

You are calling get with the wrong argument.您使用错误的参数调用 get 。

It should be:它应该是:

Object value = field.get(object);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM