Ido Barash
Ido Barash

Reputation: 5142

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

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?

Upvotes: 197

Views: 539415

Answers (11)

user7551211
user7551211

Reputation: 717

While this isn't exactly an answer for accessing values using reflection, there’s always a better and more efficient way - without reflection! At compile time, we can leverage annotation processing libraries, and by using the pojo-analyzers library we can access the getters and setters of fields without relying on reflection, making it the most performant option.

@DetailedPojo
public class MyClass {
    public String myField;
}
...
MyClass c = new MyClass("bla");
DetailedMyClass.map.get("myField").getFieldValue(c); // bla

Upvotes: 0

Danillo Evangelista
Danillo Evangelista

Reputation: 1

As an alternative of the another answers and maybe useful for some one, is use a method like this

private Double getFieldValue(String fieldName, SomeObject  someObject) {
    try {
        Field field = SomeObject.class.getDeclaredField(fieldName);
        field.setAccessible(true);
        return (Double) field.get(someObject);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        // Your error handler
    }
    return 0D;
}

Note that the return type of this method can be what you need, just change.

Upvotes: 0

Dmitry Spikhalsky
Dmitry Spikhalsky

Reputation: 5850

You should pass the object to get method of the field, so

  import java.lang.reflect.Field;

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

Upvotes: 206

Parameshwar
Parameshwar

Reputation: 966

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
 }

Upvotes: 1

RANAJEET BARIK
RANAJEET BARIK

Reputation: 185

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

Upvotes: 7

Isaias Carrera
Isaias Carrera

Reputation: 695

I post my solution in Kotlin, but it can work with java objects as well. 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/

Upvotes: 2

Marius
Marius

Reputation: 3161

Like answered before, you should use:

Object value = field.get(objectInstance);

Another way, which is sometimes prefered, is calling the getter dynamically. 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. 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);
        }
    }

Upvotes: 189

Rahul sharma
Rahul sharma

Reputation: 409

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

Upvotes: 11

silversmurf
silversmurf

Reputation: 485

I use the reflections in the toString() implementation of my preference class to see the class members and values (simple and quick debugging).

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.

Upvotes: 25

Seba
Seba

Reputation: 2319

You are calling get with the wrong argument.

It should be:

Object value = field.get(object);

Upvotes: 0

Costi Ciudatu
Costi Ciudatu

Reputation: 38265

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. So you should have 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.

Upvotes: 11

Related Questions