java 使用反射调用类中的所有 setter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10506960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:20:31  来源:igfitidea点击:

Invoking all setters within a class using reflection

javareflectioninvoke

提问by user1383163

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

我有一个域对象,出于这个问题的目的,我将使用以下私有变量调用 Person:

String name
int age

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

每个都有 getter 和 setter。现在我也有Map<String, String>以下条目:

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.

我想填充类 Person 中所有 setter 方法的列表,然后循环遍历此列表并使用地图中的值调用每个方法。

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

这是否可能,因为我在网上看不到任何与此接近的示例。非常感谢示例。

回答by ametren

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

当然有可能!您可以通过执行以下操作来获取所有以“set”开头的方法:

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?

现在你已经掌握了方法。您是否已经知道如何为您的类实例调用它们?

回答by Tomasz Nurkiewicz

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

您是否尝试过BeanUtils.populate()) 来自Apache Commons BeanUtils

BeanUtils.populate(yourObject, propertiesMap);

回答by Pawe? Skorupiński

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.beansand java.lang.reflect.

这是一个完整的解决方案,可以预先验证输出类,从而为地图包含的所有属性调用 setter。它纯粹使用java.beansjava.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;
    }
}

回答by Paul Vargas

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

我认为你可以使用一个库,Apache Commons BeanUtils。如果您有一个包含字段和值对的映射,PropertyUtils类可以帮助您:

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