利用反射批量设置对象的成员变量值,支持对象类型的成员变量

递归设置Java对象属性
本文介绍了一种使用反射机制递归地为Java对象的多级属性设置值的方法。通过提供的核心方法`setObjectValue`,可以方便地批量设置对象及其嵌套对象的属性值,即使这些对象缺少setter方法也能实现。

例如对象VisitOrder,其中有成员变量houseInfo,类型是HouseInfo,HouseInfo中有成员变量houseOwner,houseOwner类型是Customer
可以通过"houseInfo.houseOwner.id"来递归设置VisitOrder

通过如下语句可以递归设置VisitOrder对象的成员变量

 /***
     * 18/2/12
     */
    @Test
    public final void test_setObjectValue() {
        Map<String, Object> param = new HashMap<>();
        param.put("orderNo", "INS20180212125352285XPI749");
        param.put("houseInfo.id", 106);
        param.put("houseInfo.houseOwner.id",255);

        VisitOrder visitOrder = new VisitOrder();
        ReflectHWUtils.setObjectValue(visitOrder, param);//利用反射批量设置对象的成员变量值
        System.out.println("houseInfo.houseOwner.id :" +visitOrder.getHouseInfo().getHouseOwner().getId());
    }

核心方法

setObjectValue

如下:

/***
     * 利用反射设置对象的属性值. 注意:属性可以没有setter 方法.
     *
     * @param obj
     * @param params
     * @throws SecurityException
     */
    public static void setObjectValue(Object obj, Map<String, ?> params) {
        if (ValueWidget.isNullOrEmpty(obj)) {
            return;
        }
        if (ValueWidget.isNullOrEmpty(params)) {
            return;
        }
        Class<?> clazz = obj.getClass();
        for (Iterator it = params.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, ?> entry = (Map.Entry<String, ?>) it
                    .next();
            String key = entry.getKey();
            Object propertyValue = entry.getValue();
            if (ValueWidget.isNullOrEmpty(propertyValue)) {
                continue;
            }
            if (key.contains(".")) {
                setPropValueReser(obj, key, propertyValue);
            } else {
                Field name = getSpecifiedField(clazz, key);
                if (name != null) {
                    setAccessibleAndVal(obj, name, propertyValue);
                }
            }

        }

    }

    /***
     * 成员变量如果包含英文句点,则表示设置成员变量对象中属性,支持多级,例如"houseInfo.houseOwner.id"
     * @param obj
     * @param key : 成员变量名称,例如:"username","agent.id"
     * @param propertyValue
     */
    public static void setPropValueReser(Object obj, String key, Object propertyValue) {
        if (key.contains(".")) {
            String[] columns = key.split("\\.", 2);
            Field name = getSpecifiedField(obj.getClass(), columns[0]);
            Object val1 = getObjectValue(obj, name);
            if (null == val1) {
                val1 = ReflectHWUtils.createEmptyObj(name.getType());
                setAccessibleAndVal(obj, name, val1);
            }
            setPropValueReser(val1, columns[1], propertyValue);
        } else {
            setAccessibleAndVal(obj, getSpecifiedField(obj.getClass(), key), propertyValue);
        }

    }


    public static void setAccessibleAndVal(Object obj, Field f, Object str) {
        f.setAccessible(true);
        try {
            f.set(obj, str);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            logger.error("Field.set(obj, str) error", e);
            throw new LogicBusinessException(e.getMessage());
        }
    }
/***
 * Get Specified Field
 *
 * @param clazz
 * @param fieldName
 * @return
 */
public static Field getSpecifiedField(Class<?> clazz, String fieldName) {
    if (ValueWidget.isNullOrEmpty(clazz) || ValueWidget.isNullOrEmpty(fieldName)) {
        return null;
    }
    Field f = null;
    try {
        f = clazz.getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        Class superClass2 = clazz.getSuperclass();
        if (superClass2.getName().equals(Object.class.getName())) {
            return null;
        }
        return getSpecifiedField(superClass2/*
                               * may be null if it is
                               * Object .
                               */, fieldName);
        // e.printStackTrace();
    }
    return f;
}

说明:反射确认会影响性能,但是有时候很方便

参考:https://github.com/liuyu520/io0007

转载于:https://my.oschina.net/huangweiindex/blog/1621581

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值