Invoking setter method using java reflection

JavaReflection

Java Problem Overview


I need to invoke the setter methods of a class using reflection, and the code is as below:

try {             
   Method method = myObj.getClass().getMethod("set" + fieldName, new Class[] { value.getClass() });               
   method.invoke(myObj, value);
     } catch (Exception ex) {
         ex.printStackTrace();
     }

The value is an ArrayList and the setter method is as below:

public void setNames(List<String> names){
    this.names = names;
}

A java.lang.NoSuchMethodException is thrown when running this code, but when the setter method parameter type is changed to ArrayList from List it executes fine. Is there a way to keep the setter method parameter in super type and still use reflection without manually giving the type of the parameter when getting the method from the class?

Java Solutions


Solution 1 - Java

You could use BeanUtils:

Step #1

Customer customer = new Customer();

Step #2

BeanUtils.setProperty(customer,"firstName","Paul Young");

You could iterate all class members using reflection and set values accordingly, assuming customer object has:

private String firstName;
// Getter and Setter are defined

Solution 2 - Java

If you happen to use spring framework, you could use the PropertyAccessorFactory for retrieving an implementation of the PropertyAccessor interface:

Accessing properties directly

PropertyAccessor myAccessor = PropertyAccessorFactory.forDirectFieldAccess(object);
// set the property directly, bypassing the mutator (if any)
myAccessor.setPropertyValue("someProperty", "some value");

Accessing properties through accessors/mutators

If you need to access your properties using their getters and setters, you could use instead the forBeanPropertyAccess method:

PropertyAccessor myAccessor = PropertyAccessorFactory.forBeanPropertyAccess(object);
// a `setSomeProperty()` method will be used
myAccessor.setPropertyValue("someProperty", "some value");

Solution 3 - Java

Contrary to other answers, there is a really simple solution. See java.beans.Statement. It gives you a way to execute arbitrary reflective code without having to worry about actual vs formal types (and a few other things).

Solution 4 - Java

There is a simple solution, but that simplicity comes at the cost of performance.

I'm using this monster instead:

public static Method findMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {

    // First try the trivial approach. This works usually, but not always.
    try {
        return clazz.getMethod(methodName, parameterTypes);
    } catch (NoSuchMethodException ex) {
    }

    // Then loop through all available methods, checking them one by one.
    for (Method method : clazz.getMethods()) {

        String name = method.getName();
        if (!methodName.equals(name)) { // The method must have right name.
            continue;
        }

        Class<?>[] acceptedParameterTypes = method.getParameterTypes();
        if (acceptedParameterTypes.length != parameterTypes.length) { // Must have right number of parameters.
            continue;
        }

        boolean match = true;
        for (int i = 0; i < acceptedParameterTypes.length; i++) { // All parameters must be right type.
            if (null != parameterTypes[i] && !acceptedParameterTypes[i].isAssignableFrom(parameterTypes[i])) {
                match = false;
                break;
            }
            if (null == parameterTypes[i] && acceptedParameterTypes[i].isPrimitive()) { // Accept null except for primitive fields.
                match = false;
                break;
            }
        }

        if (match) {
            return method;
        }

    }

    // None of our trials was successful!
    throw new NoSuchMethodException();
}

parameterTypes are what you get from your value.getClass(). Some or all of them can be also null. Then they are treated as matces for any non-primitive parameter fields.

Even this isn't quit perfect: If there are several methods that are polymorphically suitable but none of which matches exactly, then the returned method is chosen arbitrarily (the first match in the array that clazz.getMethods() returns is taken). This behavior differs from Java the Language behavior, in which the "closest match" is always used.

If getting the method by name is sufficient (i.e. you assume that the parameters are suitable if the name matches), then you can manage with much simpler (and somewhat faster):

public static Method findMethod(Class<?> clazz, String methodName) {
  for (Method method : clazz.getMethods()) {
    if (method.getName().equals(methodName)) {
      return method;
    }
  }
  throw new NoSuchMethodException();
} 

To further boost it up, consider some sort of cache.

Solution 5 - Java

Reflection Class is sometimes called as dynamic invocation.

for example, lets look around getter methods using reflection

consider there is a class called MyReflectionClass and has a method called getreflect(). (eg type string) lets see how to use reflection classes

MyReflectionClass  obj = new MyReflectionClass();

<? extends MyReflectionClass> tempClass = obj.getClass();
String a = (String) obj.getMethod("getreflect").invoke(obj);

now setter method

(String) obj.getDeclaredMethod("setreflect", String.class).invoke(obj,"MyString");

if you need to do the same operation with sequence of string then

    (String) obj.getDeclaredMethod("setreflect",
 new String.class{}).invoke(obj,"MyString1","MyString2");

hope it may be useful

Solution 6 - Java

Example set All filds using the setters methods geting the values with ResultSet.

private Object setAllSetters(Object ob, ResultSet rs) throws SQLException{
    // MZ: Find the correct method
    Class cls = ob.getClass();
    while (rs.next()) {
        for (Field field : cls.getDeclaredFields()){
            for (Method method : cls.getMethods())
            {
                if ((method.getName().startsWith("set")) && (method.getName().length() == (field.getName().length() + 3)))
                {
                    if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
                    {
                        // MZ: Method found, run it
                        try
                        {
                            method.setAccessible(true);
                            if(field.getType().getSimpleName().toLowerCase().endsWith("integer"))
                                method.invoke(ob,rs.getInt(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("long"))
                                method.invoke(ob,rs.getLong(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("string"))
                                method.invoke(ob,rs.getString(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("boolean"))
                                method.invoke(ob,rs.getBoolean(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("timestamp"))
                                method.invoke(ob,rs.getTimestamp(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("date"))
                                method.invoke(ob,rs.getDate(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("double"))
                                method.invoke(ob,rs.getDouble(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("float"))
                                method.invoke(ob,rs.getFloat(field.getName().toLowerCase()));
                            else if(field.getType().getSimpleName().toLowerCase().endsWith("time"))
                                method.invoke(ob,rs.getTime(field.getName().toLowerCase()));
                            else 
                                method.invoke(ob,rs.getObject(field.getName().toLowerCase()));
                        }
                        catch (IllegalAccessException | InvocationTargetException | SQLException e)
                        {
                            System.err.println(e.getMessage());
                        }
                    }
                }
            }
        }
    }
    return ob;
}

Solution 7 - Java

Detecting Method Names using String Handling might not look like right way of doing it. Consider this as one of the solutions.

	try {
			Animal animal = new Animal();
			BeanInfo beaninfo = Introspector.getBeanInfo(Animal.class);
	        PropertyDescriptor pds[] = beaninfo.getPropertyDescriptors();
	        Method setterMethod=null;
	        for(PropertyDescriptor pd : pds) { 
        		setterMethod = pd.getWriteMethod(); // For Setter Method

           /*
               You can get Various property of Classes you want. 
           */

        		System.out.println(pd.getName().toString()+ "--> "+pd.getPropertyType().toString()+"--Setter Method:->"+pd.getWriteMethod().toString());
        		
        		if(setterMethod == null) continue;
        		else
        			setterMethod.invoke(animal, "<value>");
	        }
		}catch(Exception e) {e.printStackTrace();}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDilini RajapakshaView Question on Stackoverflow
Solution 1 - JavaAnandView Answer on Stackoverflow
Solution 2 - Javael.atomoView Answer on Stackoverflow
Solution 3 - Javauser207421View Answer on Stackoverflow
Solution 4 - JavaJoonas PulakkaView Answer on Stackoverflow
Solution 5 - JavaPrasanna SundaramView Answer on Stackoverflow
Solution 6 - JavaFernando RossatoView Answer on Stackoverflow
Solution 7 - JavaMitesh MananiView Answer on Stackoverflow