Reputation: 5142
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
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
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
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
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
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
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
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
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
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
Reputation: 2319
You are calling get with the wrong argument.
It should be:
Object value = field.get(object);
Upvotes: 0
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