186

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?

Abra
  • 19,142
  • 7
  • 29
  • 41
Ido Barash
  • 4,856
  • 11
  • 41
  • 78
  • 5
    Looking at the [API](http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Field.html), the argument to `field.get()` should be `object`, not `objectValue`. – akaIDIOT Nov 15 '12 at 15:01

9 Answers9

189

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);
jumping_monkey
  • 5,941
  • 2
  • 43
  • 58
Dmitry Spikhalskiy
  • 5,379
  • 1
  • 26
  • 40
  • 9
    do you know the reason why object has to be used in field.get(object) -- field itself comes from that object, why does it need it again !? – serup Jun 17 '16 at 08:19
  • 26
    @serup No, Field object comes from Class object, which has no connection with your actual instance. (```object.getClass()``` will returns you this Class object) – Dmitry Spikhalskiy Jun 17 '16 at 11:43
  • 12
    `object` in the snippet is not defined so readers can't understand how to use it. – Ghilteras Apr 03 '20 at 18:45
  • @RajanPrasad Not really. There is a single object in the question that has a name 'object'. Other objects have other names. The answer is precise and tailored for the questions and for the names that are used in the question to make things as clear as possible. If it doesn't work for you - I have no idea how to more it more clear and you should try other answers or probably avoid reflection just yet. – Dmitry Spikhalskiy Jun 13 '20 at 08:09
  • 4
    downvote. field.get(object) not clarified. What needs to be passed in `object`? – saran3h Mar 30 '21 at 07:39
  • @saran3h A variable named `object` is used in the original code snippet in the question. This `object` is that `object` from the question. The answer is tailored to the question and variable names used in the question. – Dmitry Spikhalskiy Mar 30 '21 at 20:35
  • also downvote... where is "object" in this question? – horoyoi o Sep 06 '21 at 09:40
  • @horoyoio wow. Here: ```object.getClass().getDeclaredField(fieldName);``` - it's right in the question. Do you see the `object` variable here? – Dmitry Spikhalskiy Sep 07 '21 at 04:28
186

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);
        }
    }
Marius
  • 3,043
  • 1
  • 15
  • 24
  • 2
    it seems not exactly true that you need to iterate through super classes yourself. The c.getFields() or c.getField() will automatically search the field on each implement interface and recursively through all superclasses. So just it's enough to switch to getX from getDeclaredX. – Przemysław Ładyński Nov 25 '15 at 19:50
  • 3
    Indeed, the getFields() routine will allow you to fetch the fields for all super classes and interfaces, but only the public ones. Usually, fields are made private/ protected and are exposed via getters/ setters. – Marius Nov 27 '15 at 14:49
  • 2
    @Marius, may i know what is package is the `BaseValidationObject`? – randytan Dec 09 '15 at 10:13
  • @Randytan, its contained within my private code repository, you can replace it with Object. The same applies to the static Logger calls, replace them with your own logger (instance). – Marius Dec 09 '15 at 15:05
  • 1
    @Marius the `object` class doesn't have the method `getMethods()`. Any advise? – randytan Dec 10 '15 at 04:51
  • @Randytan, the getMethods routine is a call to a (helper class) static method, posted here http://pastebin.com/NVYNEcA9 – Marius Dec 10 '15 at 14:03
  • @Marius thank you for your piece of code and advise. to sum up, i change the code into `for (Method method : getMethods(o.getClass())) {`. Is it? – randytan Dec 10 '15 at 14:22
  • 1
    `object` in the first snippet is not defined, readers can't understand how to use it. – Ghilteras Apr 03 '20 at 18:46
  • downvote. field.get(object) not clarified. What needs to be passed in `object`? – saran3h Mar 30 '21 at 07:39
25

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.

silversmurf
  • 485
  • 4
  • 11
11

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.

Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
11
 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();
 }
Jason
  • 1,658
  • 3
  • 20
  • 51
Rahul sharma
  • 399
  • 1
  • 5
  • 14
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));
`
RANAJEET BARIK
  • 185
  • 2
  • 7
2

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/

Isaias Carrera
  • 675
  • 9
  • 9
1

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
 }
Parameshwar
  • 856
  • 8
  • 16
0

You are calling get with the wrong argument.

It should be:

Object value = field.get(object);
Seba
  • 2,319
  • 15
  • 14