通过反射调用类中的所有setter方法

5

我有一个域对象,为了本问题的目的,我将其称为Person,具有以下私有变量:

String name
int age

每个都有getter和setter。现在我还有一个Map<String, String>,其中包含以下条目:
name, phil
age, 35

我想列出类Person中所有setter方法的列表,然后通过循环遍历该列表并使用Map中的值调用每个方法。
我无法在网上找到与此非常接近的示例。如果能提供示例将不胜感激。
4个回答

17

当然可以!只需通过以下方式获取以 "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);
    }
}

现在你已经有了这些方法。你知道如何为类的实例调用它们吗?


嘿,没问题。你还有其他问题吗?如果没有,你可以将其中一个答案标记为已接受吗? - ametren
1
@Krrose27 - getMethods() 方法似乎也会返回继承的公共方法,来自 javadoc: "getMethods - 返回一个包含 Method 对象的数组,反映了该 Class 对象所表示的类或接口的所有公共成员方法,包括由类或接口声明的方法以及从超类和超接口继承的方法。" - ivans
1
如果您不想在列表中包含继承的方法,请使用getDeclaredMethods()而不是getMethods()。 - Alan Feekery

2

1
这是一个完整的解决方案,它事先验证输出类,并随后为地图包含的所有属性调用设置器。它纯粹使用 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;
    }
}

0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接