BeanUtils工具类中的copyProperties方法使用「建议收藏」

BeanUtils工具类中的copyProperties方法使用「建议收藏」文章目录1、两个包下的BeanUtils.copyProperties对比2、BeanUtils.copyProperties的深浅拷贝问题2.1、浅拷贝和深拷贝2.2、BeanUtils.copyProperties深浅拷贝问题1、两个包下的BeanUtils.copyProperties对比BeanUtils是开发中常用到的工具类,而获取这一工具类主要是通过导入org.springframework.beans.BeanUtils或者org.apache.commons.beanutils.Bean

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1、两个包下的BeanUtils.copyProperties对比

BeanUtils是开发中常用到的工具类,而获取这一工具类主要是通过导入org.springframework.beans.BeanUtils或者org.apache.commons.beanutils.BeanUtils包来获取,但是不同的包中BeanUtils的方法使用是不一样的,接下来就对这两个包中的copyProperties方法进行对比。

先来看一下这两个包中的copyProperties方法的定义:

//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){ 
   ....}

由定义可知,在org.springframework.beans.BeanUtils包下的copyProperties第一个参数是被copy的对象,而org.apache.commons.beanutils.BeanUtils中是第二个参数,所以使用时不要弄混。

1)接下来定义两个实体类Student和Teacher,用来模拟目标对象(target/dest)中包含被copy的对象(source/orig)的所有字段时

@Data
public class Student { 
   
	private String id;
	private String name;
	private String age;
    
    public Student(String id, String name, String age) { 
   
		this.id = id;
		this.name = name;
		this.age = age;
	}
}

@Data
public class Teacher { 
   
	private String id;
	private String name;
	private String age;
	private String sex;   //多出来的参数

    public Teacher() { 
   }
	public Teacher(String id, String name, String age, String sex) { 
   
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}	
}

先使用org.springframework.beans.BeanUtils下的copyProperties来进行测试,执行代码如下:

import org.springframework.beans.BeanUtils;

public static void main(String[] args) throws Exception { 
   
	Student student = new Student(UUID.randomUUID().toString(), "zhangsan", "19");
	Teacher teacher = new Teacher();
	System.out.println(student.toString());
	BeanUtils.copyProperties(student,teacher);
	System.out.println(teacher.toString());
}
执行结果如下:
	Student(id=00c47e77-785d-4939-89db-e757979050ec, name=zhangsan, age=19)
	Teacher(id=00c47e77-785d-4939-89db-e757979050ec, name=zhangsan, age=19, sex=null)

当将引入的包改为org.apache.commons.beanutils.BeanUtils时,将上述中的执行代码进行如下修改:

BeanUtils.copyProperties(teacher,student); //因为apache包下被copy的参数在第二个位置
执行结果如下:
	Student(id=900d0b93-1913-4022-b86b-127682cd9f5c, name=zhangsan, age=19)
	Teacher(id=00c47e77-785d-4939-89db-e757979050ec, name=zhangsan, age=19, sex=null)

小结:当目标对象(target/dest)中包含被copy的对象(source/orig)的所有字段时,两种包下的copyProperties方法均可以执行成功。

2)对上述中说到的实体类进行修改,即目标对象(target/dest)中不包含被copy的对象(source/orig)的所有字段时,修改后的内容如下:

@Data
public class Student { 
   
	private String id;
	private String name;
	private String age;
    
    public Student(String id, String name, String age) { 
   
		this.id = id;
		this.name = name;
		this.age = age;
	}
}

@Data
public class Teacher { 
   
	private String id;
	private String name;
    
	public Teacher() { 
   }
	public Teacher(String id, String name) { 
   
		this.id = id;
		this.name = name;
	}	
}

执行代码与1)中的一样这里就不写了,先使用org.apache.commons.beanutils.BeanUtils中的copyProperties方法,执行结果如下:

    Student(id=6f6711ef-fa2f-420d-b0b3-b76998356533, name=zhangsan, age=19)

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/FastHashMap
        at org.apache.commons.beanutils.PropertyUtilsBean.getPropertyDescriptor(PropertyUtilsBean.java:964)
        at org.apache.commons.beanutils.PropertyUtilsBean.isWriteable(PropertyUtilsBean.java:1479)
        at org.apache.commons.beanutils.BeanUtilsBean.copyProperties(BeanUtilsBean.java:280)
        at org.apache.commons.beanutils.BeanUtils.copyProperties(BeanUtils.java:135)
        at com.learn.controller.BeanController.main(BeanController.java:39)
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.FastHashMap
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 5 more

接下来使用org.springframework.beans.BeanUtils下的copyProperties方法,执行结果如下:

    Student(id=87665c46-9a6f-4936-9c9d-1513e29f2bca, name=zhangsan, age=19)
    Teacher(id=87665c46-9a6f-4936-9c9d-1513e29f2bca, name=zhangsan)

小结:目标对象(target/dest)中不包含被copy的对象(source/orig)的所有字段时,应选用org.springframework.beans.BeanUtils下的copyProperties方法

3)基于2)中的实体类来看下另外一种情况,修改下执行代码,实体类不变:

	public static void main(String[] args) throws Exception { 
   
		Student student = new Student(UUID.randomUUID().toString(), "zhangsan", "19");
		Teacher teacher = new Teacher("12334","lisi");
		System.out.println(student.toString());
		BeanUtils.copyProperties(student,teacher);
		System.out.println(teacher.toString());
	}

先使用org.apache.commons.beanutils.BeanUtils中的copyProperties方法,执行结果如下:

Student(id=16bf375a-5925-4411-8bdf-158b3373d261, name=zhangsan, age=19)
Teacher(id=12334, name=zhangsan)
Student(id=12334, name=zhangsan, age=19)

接下来使用org.springframework.beans.BeanUtils下的copyProperties方法,执行结果如下:

Student(id=2df2fba9-22a2-4cb6-86d7-3d5b47475114, name=zhangsan, age=19)
Teacher(id=12334, name=zhangsan)
Student(id=12334, name=zhangsan, age=19)

小结:目标对象(target/dest)中包含被copy的对象(source/orig)的所有字段时,两个包下的copy方法都可以,而且目标对象(target/dest)中多于的对象的值不会被覆盖掉。

总结:

​ 1、org.apache.commons.beanutils.BeanUtils和org.springframework.beans.BeanUtils两个包中的copyProperties方法目标对象和源对象参数的位置是相反,使用时需要注意。

​ 2、使用org.apache.commons.beanutils.BeanUtils进行copy对象时,被copy的对象(source/orig)中包含的字段目标对象(target/dest)必须包含,可以有其他的多于字段,类型可以不相同,但字段名称必须一致;org.springframework.beans.BeanUtils中的没有这个限制。

2、BeanUtils.copyProperties的深浅拷贝问题

2.1、浅拷贝和深拷贝

先来说一下什么是浅拷贝,深拷贝;两者最主要的区别就在于是否是复制了对象的真实实体还是说只是使用了一个指针,两者指向的是内存中的同一个对象。

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址;

深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存;同时如果一个类中包含有引用类型变量,则该类拷贝以后引用类型也会被拷贝。

参考博文:
1、深拷贝和浅拷贝的区别
2、java中clone方法的理解(深拷贝、浅拷贝)
3、System.arraycopy()使用原理解析,坑点之:深拷贝和浅拷贝

2.2、BeanUtils.copyProperties深浅拷贝问题

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

新增加一个实体类Life,接下来我们将上述中的代码进行一个改造:

@Data
public class Life { 
   
	private String life;

	public Life(String life) { 
   
		this.life = life;
	}
}
@Data
public class Teacher { 
   
	private String id;
	private String name;
	private Life life;

	public Teacher(String id, String name) { 
   
		this.id = id;
		this.name = name;
	}
	public Teacher() { 
   }
}

@Data
public class Student { 
   
	private String id;
	private String name;
	private String age;
	private Life life;
    
    public Student(String id, String name, String age) { 
   
		this.id = id;
		this.name = name;
		this.age = age;
	}
}
import org.springframework.beans.BeanUtils;
public class BeanController { 
   

	public static void main(String[] args) throws Exception { 
   
		Student student = new Student(UUID.randomUUID().toString(), "zhangsan", "19");
		Life life=new Life("young");
		student.setLife(life);
		Teacher teacher = new Teacher();
		System.out.println(student.toString());
		BeanUtils.copyProperties(student,teacher);
		teacher.getLife().setLife("old");
		System.out.println(student.toString());
	}
}
执行结果如下:
	Student(id=988cac88-638c-4e52-8421-db39590ed32c, name=zhangsan, age=19, life=Life(life=young))
Student(id=988cac88-638c-4e52-8421-db39590ed32c, name=zhangsan, age=19, life=Life(life=old))

正常情况下,Student中的life值应该为young,但是student拷贝给teacher以后,随着teacher中life修改,student中的life也被修改,说明teacher和student两个对象中的life子对象为内存中的同一个life对象,所以BeanUtils.copyProperties属于浅拷贝。

参考博文:BeanUtils.copyProperties深拷贝的使用

3、深拷贝的方法

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

	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)实现深拷贝

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/186226.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • trunk链路的配置命令_链路聚合配置

    trunk链路的配置命令_链路聚合配置实验环境使用之前用过的GNS3、WireShark和CRT进入GNS3页面,点击左侧图标菜单栏,拖入2台路由器到拓扑操作台,再点击PC图标,选择VPC,拖入拓扑操作台,配置两台路由器(更改名称、更改图标、添加二层业务单板、添加磁盘容量为128Mb)—————-配置环境————-1、接下来用网线把PC和路由器连接起来将PC1连到SW1的f1/0将PC2连…

    2022年10月29日
  • 如何提高OKCC呼叫中心坐席利用率

    如何提高OKCC呼叫中心坐席利用率说到底,呼叫中心是经营人的一个行业,是劳动密集型的一个典型场景。但凡是劳动密集型行业,都有一个典型特点,就是毛利偏低,效率提高或降低5到10个点,往往就是赚钱、白干甚至亏本的分界线。也正是因为如此,不管是呼入客服型,还是外呼电销型,坐席利用率,都是衡量呼叫中心管理效率的核心指标之一。坐席利用率,是坐席投入工作的有效时长占上班总时长的比例。投入工作的时间,主要包括接打电话的时间以及用于记录电话交流信息的话后处理时间,这部分时间再加上用餐、休息、培训及会议、总结交流等时间,即是坐席一天的工作总时间。显

    2022年7月12日
  • Java截取String字符串的几种方法

    Java截取String字符串的几种方法方法一,指定字符,截取字符串,返回字符串数组:Stringstr=”abcd,123,123abc,fij23″;String[]strs=str.split(“,”);方法二,指定索引号,截取字符串:将字符串从索引号为5开始截取,一直到字符串末尾。(索引值从0开始):Stringstr=”abcdefghijklmnopqrstuvwxyz”;str.substri…

    2022年5月19日
  • 光栅化 (Rasterization)

    光栅化 (Rasterization)上一篇文章讨论了如何在多边形的某一点上分配光强度值,这里主要讨论如何为多边形确定实际的像素,即在栅格屏幕上的对应位置,这个过程称为光栅化(Rasterization)或者扫描转换(Scanconv

    2022年8月4日
  • Unreal Engine 4 C++ 能够创建角色Zoom摄像头(资源)

    Unreal Engine 4 C++ 能够创建角色Zoom摄像头(资源)

    2022年1月14日
  • mos管开关工作原理图解_双光耦开关电源电路图

    mos管开关工作原理图解_双光耦开关电源电路图在使用MOS管设计开关电源或者马达驱动电路的时候,大部分人都会考虑MOS的导通电阻,最大电压等,最大电流等,也有很多人仅仅考虑这些因素。这样的电路也许是可以工作的,但并不是优秀的,作为正式的产品设计也是不允许的。下面是我对MOSFET及MOSFET驱动电路基础的一点总结,其中参考了一些资料,非全部原创。包括MOS管的介绍,特性,驱动以及应用电路。1、MOS管种类和结构MOSFET管是FET的…

    2022年9月20日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号