Instead of trying to call a setter, you could also just directly set the value to the property using reflection. For example:
public static boolean set(Object object, String fieldName, Object fieldValue) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, fieldValue);
return true;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return false;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
set(instance, "salary", 15);
set(instance, "firstname", "John");
FYI, here is the equivalent generic getter:
@SuppressWarnings("unchecked")
public static <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return (V) field.get(object);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return null;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
int salary = get(instance, "salary");
String firstname = get(instance, "firstname");
Answer from sp00m on Stack OverflowInstead of trying to call a setter, you could also just directly set the value to the property using reflection. For example:
public static boolean set(Object object, String fieldName, Object fieldValue) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, fieldValue);
return true;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return false;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
set(instance, "salary", 15);
set(instance, "firstname", "John");
FYI, here is the equivalent generic getter:
@SuppressWarnings("unchecked")
public static <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return (V) field.get(object);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return null;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
int salary = get(instance, "salary");
String firstname = get(instance, "firstname");
To update the first name
- First find the field you want to update
- Then find the mutator (which accepts an argument of the field's type)
- Finally execute the mutator on the object with the new value:
Field field=classHandle.getDeclaredField("firstName");
Method setter=classHandle.getMethod("setFirstName", field.getType());
setter.invoke(myObject, "new value for first name");
Videos
If your classes respect the JavaBeans convention (standard getters and setters encapsulate fields), you can use the Introspector, and several frameworks that rely on it.
My favorite example would be Spring's BeanWrapper technology, which allows you to write code like this:
BeanWrapper bw = new BeanWrapperImpl(street);
bw.setPropertyValue("buildings[0].appartments[1].owner", "luke");
I have just do a simply solution based on your Structure. This have a lot to be add (NullPointerException, OutOfBounds, ...) but for correct input, you have a correct answer.
Then you just need to methods, one to set a value, one to get a instance from a list. Both need to use reflection.
public Object getListItem(Object o, String name, int index) throws Exception{
return ((List)o.getClass().getDeclaredField(name).get(o)).get(index);
}
public void setValue(Object o, String name, Object value) throws Exception{
o.getClass().getDeclaredField(name).set(o, value);
}
Like a said, no checks are made, I did simple since I do that from scratch.
Then, just need to parse the String (again, no check) based on / to find each [variable/value] blocs. And find what type this is :
- if it contains
#, this is an attribution - if it contains
., this is a getter in a list
So this should looks like this.
public void init(Object o, String pattern) throws Exception{
String[] array = pattern.split("/");
for(String s : array){
if(s.contains("#")){
String[] param = s.split("\\#");
setValue(o, param[0], param[1]);
} else {
String[] list = s.split("\\.");
o = getListItem(o, list[0], Integer.parseInt(list[1]));
}
}
}
Following is the output from the example you can find on ideone here
That will output
[Street] Foo [
[Building] 1 1[[Apartment] null, [Apartment] null],
[Building] 2 2[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null],
[Building] 3 1[[Apartment] null, [Apartment] null]]
[Street] Foo [
[Building] 1 1[[Apartment] null, [Apartment] null],
[Building] 2 3[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null],
[Building] 3 1[[Apartment] null, [Apartment] null]]
[Street] Foo [
[Building] 1 1[[Apartment] null, [Apartment] null],
[Building] 2 3[[Apartment] null, [Apartment] null, [Apartment] null, [Apartment] null],
[Building] 3 1[[Apartment] null, [Apartment] John]]
Hopefully this is what you are trying to do:
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
private Map ttp = new HashMap();
public void test() {
Field declaredField = null;
try {
declaredField = Test.class.getDeclaredField("ttp");
boolean accessible = declaredField.isAccessible();
declaredField.setAccessible(true);
ConcurrentHashMap<Object, Object> concHashMap = new ConcurrentHashMap<Object, Object>();
concHashMap.put("key1", "value1");
declaredField.set(this, concHashMap);
Object value = ttp.get("key1");
System.out.println(value);
declaredField.setAccessible(accessible);
} catch (NoSuchFieldException
| SecurityException
| IllegalArgumentException
| IllegalAccessException e) {
e.printStackTrace();
}
}
public static void main(String... args) {
Test test = new Test();
test.test();
}
}
It prints :
value1
It's worth reading Oracle Java Tutorial - Getting and Setting Field Values
Field#set(Object object, Object value) sets the field represented by this Field object on the specified object argument to the specified new value.
It should be like this
f.set(objectOfTheClass, new ConcurrentHashMap<>());
You can't set any value in null Object If tried then it will result in NullPointerException
Note: Setting a field's value via reflection has a certain amount of performance overhead because various operations must occur such as validating access permissions. From the runtime's point of view, the effects are the same, and the operation is as atomic as if the value was changed in the class code directly.
To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:
CopyClass<?> clazz = Child.class;
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
Using FieldUtils from the Apache Commons Lang 3:
CopyFieldUtils.writeField(childInstance, "a_field", "Hello", true);
The true forces it to set, even if the field is private.
Use Class#newInstance().
Class<TypeA> cls = TypeA.class;
TypeA typeA = cls.newInstance();
Or, in your specific case when you have to determine the type of the method parameter:
Class<?> cls = setterMethod.getParameterTypes()[0];
Object value = cls.newInstance();
setterMethod.invoke(bean, value);
You can learn more about reflection in Sun tutorial on the subject. That said, classnames ought to start with uppercase. I've corrected it in the above example.
By the way, instead of reinventing the Javabean reflection wheel, you may find one of the tools mentioned here useful as well.
Use getDeclaredFields() method in the Class object, to get all fields, then use field.set(classInstance, value) to set the value of field in an instance. Note: you may have to set the accessible flag on the field to true, if the field is private. No need to rely on setter methods.
I think I may be overthinking this problem (i.e., I shouldn't be using reflection to set variables in this way)
Yep. Reflection is fairly slow and should only be used as a last resort. If this is simply to avoid having so much redundant code, consider using automatic code generation. For pure data objects, I would strongly recommend using protocol buffers; it will generate the getters / setters (you only need to declare the fields). Plus it allows for easy communication of the data between C++, Java, and Python.
If you have a class that has a lot of fields but isn't a pure data object... well
- You should consider whether all the fields should be mutable. (Do you really need setters?)
- Whether the fields should even be visible. (Do you need any accessors at all?)
It is often a good idea to make fields "final", initialize them in the constructor(s), and provide no access or provide limited access through an implemented interface.
Using setter methods is the accepted way to set values for class member variables, reflection should definitely not be used for that as the code will be harder to understand and run much more slowly.
Most IDEs (eg Eclipse or NetBeans) include tools for automatically creating getter and setter methods for a class's fields.
Reflection seems a very fragile and non-intuitive way to implement this. Instead I think you should be telling the objects what to do, and they will collaborate between themselves to determine this. e.g.
restaurant.switchToSpringMenu();
and the Restaurant object could swap between menu instances that it has.
Exact requirement is that I will be getting some task to be done and corresponding value.. Now every task can be at different level in the hierarchy of the class... So I am not how else should I implement this
Perhaps this could be achieved via a visitor pattern. e.g. you do something like:
restaurant.reorganise(forSummer);
where forSummer is some implementation of a task. The Restaurant object collaborates with this task object, then calls on the underlying Employee/Menu classes, which will do the same.
If you really want a more generic means of navigating these hierarchies, you could look at JXPath, which allows you to use XPath-like expressions to find objects e.g.
(Ingredient)JXPathContext.newContext(restaurants).
getValue("restaurant[address/zipCode='90210']/menu/ingredients[1]");
This is a very bad idea. You shouldn't be doing this. If you really want to do this, stop using java -- it's totally inappropriate for the task at hand. You seem to not understand OO -- if you did you wouldn't be asking this question. Java, despite its common misuses, is an OO language and should be treated as such.
The first thing you should try is polymorphism. Have all the classes implement a basic tree/graph interface and a setValue() method that sets the value on the given object and walks the graph to each related object also calling setValue().
The next thing you should try is an event driven approach. Have objects register as event handlers, then raise an event containing the value to be set. Have the handlers set the appropriate values in the appropriate way.
If you use reflection you'll end up with unreadable/unmaintainable code that is very error prone and which will probably stop working as soon as you upgrade java or change a class. It will have a very short shelf-life.