BeanUtils.copyProperties 踩坑

1,448 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

简介

我们在开发中经常遇到,把父类的属性拷贝到子类中。通常有2种方法:

  1. 一个一个set
  2. 用BeanUtils.copyProperties

很显然BeanUtils更加方便,也美观很多。

==值得注意的是BeanUtils.copyProperties有俩个spring,apache不同的包,不同的包中BeanUtils的方法使用是不一样的。==

//org.springframework.beans.BeanUtils
public static void copyProperties(Object source, Object target){....}

//org.apache.commons.beanutils.BeanUtils
public static void copyProperties(Object dest,Object orig){....}

区别

  1. 在spring包下的copyProperties第一个参数是被copy的对象,而apache中是第二个参数,所以使用时不要弄混。
  2. 使用apache的进行copy对象时,被copy的对象(source/orig)中包含的字段目标对象(target/dest)必须包含,可以有其他的多于字段,类型可以不相同,但字段名称必须一致,spring中的没有这个限制。

深浅拷贝问题

BeanUtils.copyProperties使用起来虽然方便,==但是它其实只是浅拷贝==,所以类中都是单一的属性,如果类中包含有其他的子类就需要考虑下拷贝后目标对象(target/dest)中包含被copy的对象(source/orig)中的子类是否有可能被修改,如果有可能被修改就不能直接使用。

这里介绍一种深拷贝的方法,先将集合转化为字节数组输出流,然后在读取,这样就可以实现深度拷贝,代码如下:

	public <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
		// 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
	    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
	    ObjectOutputStream out = new ObjectOutputStream(byteOut);  
	    out.writeObject(src);  
	  
	    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
	    ObjectInputStream in = new ObjectInputStream(byteIn);  
	    @SuppressWarnings("unchecked")  
	    List<T> dest = (List<T>) in.readObject();  
	    return dest;  
	}  

参考文章:序列化(Serialization)实现深拷贝