利用反射来对属性进行赋值操作
工作的时候,由于业务需要,需要将某个类的一个实例化对象的某些字段【在本文中也叫属性】赋值到该类的另一个实例化对象上。
比如下面这个类:
@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。
origin则相反,上述字段在该对象中值为空。现在想要将origin中的有值的这些字段转移给destination。
一个个去赋值?这么多字段,头都大了,以后万一再加或者减几个字段,到时候还得改,这时候就可以用反射来做了。
思路,我先拿到这个类的所有属性值,遍历这些属性,在循环中拿到一个属性后,根据属性名字的名称找到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();
另外分享今天看到的很有感触的一句话:“每次回去看他们,这一座座坟茔都是在提示着生命的每一分钟都弥足珍贵。”
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END