Invoking all setters within a class using reflection

谁说胖子不能爱 提交于 2019-11-27 07:11:45

问题


I have a domain object, that for the purposes of this question I will call Person with the following private variables:

String name
int age

Each of these have getters and setters. Now I also have a Map<String, String> with the following entries:

name, phil
age, 35

I would like to populate a list of all setter methods within the class Person and then looping through this list and invoking each method using the values from the map.

Is this even possible as I cannot see any examples close to this on the net. Examples are very much appreciated.


回答1:


Sure it's possible! You can get all methods that start with "set" back by doing this:

Class curClass = myclass.class;
Method[] allMethods = curClass.getMethods();
List<Method> setters = new ArrayList<Method>();
for(Method method : allMethods) {
    if(method.getName().startsWith("set")) {
        setters.add(method);
    }
}

Now you've got the methods. Do you already know how to call them for your instance of the class?




回答2:


Have you tried BeanUtils.populate()) from Apache Commons BeanUtils?

BeanUtils.populate(yourObject, propertiesMap);



回答3:


I think you could use a library, the Apache Commons BeanUtils. If you have a map that contains field and value pairs, the class PropertyUtils can help you:

Person person = new Person();
for(Map.Entry<String, Object> entry : map.entrySet())
    PropertyUtils.setProperty(person, entry.getKey(), entry.getValue());



回答4:


This is a full solution that verifies output class beforehand and consequently calls setters for all the properties that the map contains. It uses purely java.beans and java.lang.reflect.

public Object mapToObject(Map<String, Object> input, Class<?> outputType) {
    Object outputObject = null;
    List<PropertyDescriptor> outputPropertyDescriptors = null;
    // Test if class is instantiable with default constructor
    if(isInstantiable(outputType) 
            && hasDefaultConstructor(outputType)
            && (outputPropertyDescriptors = getPropertyDescriptors(outputType)) != null) {
        try {
            outputObject = outputType.getConstructor().newInstance();
            for(PropertyDescriptor pd : outputPropertyDescriptors) {
                Object value = input.get(pd.getName());
                if(value != null) {
                    pd.getWriteMethod().invoke(outputObject, value);
                }
            }
        } catch (InstantiationException|IllegalAccessException|InvocationTargetException|NoSuchMethodException e) {
            throw new IllegalStateException("Failed to instantiate verified class " + outputType, e);
        }
    } else {
        throw new IllegalArgumentException("Specified outputType class " + outputType + "cannot be instantiated with default constructor!");
    }
    return outputObject;
}

private List<PropertyDescriptor> getPropertyDescriptors(Class<?> outputType) {
    List<PropertyDescriptor> propertyDescriptors = null;
    try {
        propertyDescriptors = Arrays.asList(Introspector.getBeanInfo(outputType, Object.class).getPropertyDescriptors());
    } catch (IntrospectionException e) {
    }
    return propertyDescriptors;
}

private boolean isInstantiable(Class<?> clazz) {
    return ! clazz.isInterface() && ! Modifier.isAbstract(clazz.getModifiers());
}

private boolean hasDefaultConstructor(Class<?> clazz) {
    try {
        clazz.getConstructor();
        return true;
    } catch (NoSuchMethodException e) {
        return false;
    }
}


来源:https://stackoverflow.com/questions/10506960/invoking-all-setters-within-a-class-using-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!