Loading...
墨滴

爱久弥新

2021/04/19  阅读:18  主题:默认主题

利用反射get、set方法给属性进行赋值

利用反射来对属性进行赋值操作

工作的时候,由于业务需要,需要将某个类的一个实例化对象的某些字段【在本文中也叫属性】赋值到该类的另一个实例化对象上。

比如下面这个类:

@Data
public class DeliveryOrderPopWinDTO {
    @JsonProperty("VBELN")
    private String VBELN;//交货单
    @JsonProperty("KUNNR")
    private String KUNNR;//客户代码
    @JsonProperty("NAME1")
    private String NAME1;//客户全称
    @JsonProperty("MATNR")
    private String MATNR;//物料代码
    @JsonProperty("ARKTX")
    private String ARKTX;//物料名称
    @JsonProperty("ERDAT")
    private String ERDAT;//创建日期
    @JsonProperty("WBSTK")
    private String WBSTK;//状态
    @JsonProperty("VGBEL")
    private String VGBEL;//发货任务号

    private String cmpsaporder;//公司间采购订单
    private String salsaporder;//销售订单
    private String deliveryOrder;//发货单
    private String pdtask;//生产任务号
    private String pdtaskDesc;//生产任务描述
    private String amount;//数量[发货量]
    private String outlgort;//出仓库-库位
    private String inlgort;//入仓库
}

不用纠结为啥有的属性全大写,有的是驼峰及其注释风格哈,这些不是本文关注点。现在假设DeliveryOrderPopWinDTO有两个对象,暂且称为destination[目的地]和origin[源头]。以下字段在destination中不为空,有值了(这个值是来自数据库的,当然本文并不用关心这些值是咋来的),剩下的字段为null。

image-20210419200239790
image-20210419200239790

origin则相反,上述字段在该对象中值为空。现在想要将origin中的有值的这些字段转移给destination。

image-20210419201313306
image-20210419201313306

一个个去赋值?这么多字段,头都大了,以后万一再加或者减几个字段,到时候还得改,这时候就可以用反射来做了。

思路,我先拿到这个类的所有属性值,遍历这些属性,在循环中拿到一个属性后,根据属性名字的名称找到origin对象中这个属性的get方法,然后调用这个get方法判断这个属性在该对象[origin]中是否有值,如果有值那么再根据属性名称找到destination对象中的这个属性的set方法,然后调用这个set方法来给destination对象中的当前属性赋值。

code:

//部分字段[把pmpp查出的数据向Hana中]的复制,为了代码优雅性,考虑用反射来做
private void copyOriginToDestination(DeliveryOrderPopWinDTO origin, DeliveryOrderPopWinDTO destination) {
    Class cls = origin.getClass();
    
    //获得属性值
    Field[] fields = cls.getDeclaredFields();

    //遍历其中的属性
    for (Field field : fields) {
        try{
            String fieldName = initStr(field.getName());
            //从origin中拿到该值
            Method getMethodOrigin = cls.getMethod("get"+fieldName);
            if(!ObjectUtils.isEmpty(getMethodOrigin.invoke(origin))){
                //如果该值不为空,则调用destination的该属性的setter 进行赋值
                Method setMethodDestination = cls.getMethod("set"+fieldName,field.getType());
                setMethodDestination.invoke(destination,getMethodOrigin.invoke(origin));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

// 将单词的首字母大写
private String initStr(String old){
    String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
    return str ;
}

几个关键点:

  • 获取get方法时一定注意get方法的驼峰规则,即属性名的第一个字母是大写,set方法同理。
  • 获取set方法的时候注意加上属性的类型作为getMethod的第二个参数,一定不要写死。
  • 当属性在类中是private修饰的时候,要用getDeclaredFields()方法,而不是getFields();

另外分享今天看到的很有感触的一句话:“每次回去看他们,这一座座坟茔都是在提示着生命的每一分钟都弥足珍贵。”

爱久弥新

2021/04/19  阅读:18  主题:默认主题

作者介绍

爱久弥新