日期:2023-09-29 18:45
在我们日常开发中,经常会涉及到DO、DTO、VO对象属性拷贝赋值。很容易想到 org.springframework.beans.BeanUtilscopyProperties 。它会通过反射机制自动获取源对象和目标对象的属性并复制对应的属性值。可以减少手动编写属性复制代码的工作量,提高代码的可读性和可维护性。
DO、DTO、VO
org.springframework.beans.BeanUtils
copyProperties
但是你知道吗?使用 BeanUtils 的 copyProperties 时存在几个陷阱。今天就让我来盘点一下:
BeanUtils
@Data public class SourceBean { 私人 年龄大; } @Data 公共 类 TargetBean { 私有琴弦年龄; } 公共 班级 测试 { 公共 静态 void main(String[] args) { 来源Bean来源=newSourceBean(); source.setAge(25L); TargetBean target = new TargetBean(); BeanUtils.copyProperties(源,目标); System.out.println(target.getAge()); //复印赋值失败,输出null } }
在上述demo中,源对象SourceBean的age属性是一个Long 类型,而目标对象TargetBean 的age属性是一个String类型。由于类型不匹配,BeanUtils.copyProperties不会评判成功的。我 演示的结果,控制台输出null。
demo
SourceBean
age
Long 类型,而目标对象TargetBean 的age属性是一个String类型。由于类型不匹配,BeanUtils.copyProperties不会评判成功的。我 演示
TargetBean
String
BeanUtils.copyProperties
null
我先回顾一下,什么是深拷贝?什么是浅拷贝?
浅拷贝是指创建一个与原对象具有相同属性值的新对象,但对于引用类型的属性仍然共享相同的引用。换句话说,浅拷贝仅复制对象及其引用,而不复制引用所指向的对象本身。
深拷贝是指创建一个与原对象具有相同属性值的新对象,包括引用类型的属性。深拷贝会递归地复制引用对象并创建一个全新的对象,以确保复制的对象与原始对象完全独立。
我再给你一个代码demo给大家看:
公共 类 地址 { 私人 字符串城市; //getter 和 setter 方法简洁 } public class 人 { private 字符串名称; 私人地址地址; //getter 和 setter 方法简洁 } Person sourcePerson = new人(); sourcePerson.setName("约翰"); 地址地址=新地址(); address.setCity("纽约"); sourcePerson.setAddress(地址); 人 targetPerson = new Person(); BeanUtils.copyProperties(sourcePerson, targetPerson); sourcePerson.getAddress().setCity("伦敦"); System.out.println(targetPerson.getAddress().getCity()); //输出为“伦敦”
在上面的示例中,源对象 Person 的属性 address 是引用类型。使用 BeanUtils.copyProperties 方法进行属性复制时,实际上仅复制引用,即 address 属性引用和源对象 地址sourcePerson 的 属性引用指向同一对象。因此,当源对象的 address 对象被修改时,目标对象的 address 对象也会被修改。
Person
address
地址sourcePerson
大家在日常开发中要注意这个陷阱哦~
公共 类 SourceBean { 私有 字符串用户名; //省略 getter 和 setter 方法 } public class TargetBean { private 字符串用户名; //省略 getter 和 setter 方法 } SourceBean source = new Source Bean(); source.setUsername("采蜗牛小男孩"); TargetBean 目标 = new TargetBean(); BeanUtils.copyProperties(源, 目标); 系统.out。 println(target.getUserName()); //输出为空
在上例中,源对象SourceBean的属性名称为用户名,目标对象TargetBean的属性名称也为 用户名。 但是,两个用户名,一个N大写,一个n小写,即属性名称不一致,BeanUtils。复制属性 方法不能自动映射这些属性(无法进行忽略大小写的自动映射),因此目标对象的 userName 属性值为 null。
用户名
BeanUtils。复制属性
userName
大家在日常开发中要注意这个陷阱哦~比如大小写不一致,一两个字母不同等等。
@Data public class SourceBean { private 字符串名称; 私有 字符串地址; } @Data 公共 类 TargetBean { 私有字符串名称; 私有 字符串地址; } SourceBean 源 = newSourceBean(); source.setName("约翰"); source.setAddress(null); TargetBean target = newTargetBean(); target.setAddress("田螺地址"); BeanUtils.copyProperties(源,目标); System.out.println(target.getAddress()); // 输出为 null
在上述示例中,源对象 SourceBean 的地址属性设置默认为null。情况下,BeanUtils.copyProperties方法将源对象中的null值属性覆盖到目标对象中。因此,目标对象的地址属性值也为null。
如果不想让空值覆盖目标对象中的属性,可以使用BeanUtils.copyProperties方法的重载方法,并传入自定义的ConvertUtilsBean 实例。配置。
ConvertUtilsBean
BeanUtils.copyProperties实际上有两个包,分别是spring和apache。请注意,这两个包有点不同:
spring和apache
使用时要注意引入的是哪个BeanUtils,并写入对应的参数位置。
SourceBean和TargetBean都有一个属性isTianLuo,它们的数据类型不变,但一个是基本类型boolean,一个为包装类型布尔值
SourceBean和TargetBean
isTianLuo
boolean
布尔值
@Data 公共 类 SourceBean { 私有 布尔值是田螺; } @Data 公共 类目标Bean { 私人布尔为田螺; }
当我运行测试应用程序时,我发现分配不正确:
SourceBean 源 = new SourceBean(); source.setTianLuo(true); TargetBean target = newTargetBean(); BeanUtils.copyProperties(源,目标); System.out.println(target.getIsTianLuo()); //输出为空
为什么?即使它是包装类型、基本类型,它也应该是可赋值的。
关灯