<!-- apache中BeanUtils的依赖 org.apache.commons.beanutils.BeanUtils.copyProperties -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- 创建springboot项目 org.springframework.beans.BeanUtils -->
说明:BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度
spring包中实践
BeanUtils.copyProperties()作用
官方解释:Copy the property values of the given source bean into the target bean
将给定源bean的属性值复制到目标bean中
A.java
package com.geekmice.onetomany.copyproperties;
import java.util.Date;
public class A {
private String userName;
private Integer age;
private Date bornDate;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBornDate() {
return bornDate;
}
public void setBornDate(Date bornDate) {
this.bornDate = bornDate;
}
@Override
public String toString() {
return "Student{" +
"userName='" + userName + '\'' +
", age=" + age +
", bornDate=" + bornDate +
'}';
}
}
B.java
package com.geekmice.onetomany.copyproperties;
import java.util.Date;
public class B {
private String userName;
private Integer age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "B{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
单元测试
/**
* 拷贝前后同一类对象,也就是拷贝前后字段是一样
*/
@Test
void t1() {
A student = new A();
student.setAge(18);
student.setBornDate(new Date());
student.setUserName("小王");
A tempStudent = new A();
System.out.println("源对象:" + student);
BeanUtils.copyProperties(student, tempStudent);
System.out.println("目标对象:" + tempStudent);
}
// 源对象:Student{userName='小王', age=18, bornDate=Wed Aug 10 20:44:59 CST 2022}
// 目标对象:Student{userName='小王', age=18, bornDate=Wed Aug 10 20:44:59 CST 2022}
/**
* 拷贝前后不是一类对象,也就是拷贝前后字段不太一样
* 只有相同的字段才会拷贝过来
*/
@Test
void t2() {
B b1 = new B();
b1.setAge(99);
b1.setUserName("小红");
A a = new A();
System.out.println("源对象:" + b1);
BeanUtils.copyProperties(b1, a);
System.out.println("目标对象:" + a);
A a1 = new A();
a1.setUserName("小李");
a1.setAge(18);
a1.setBornDate(new Date());
B b2 = new B();
b2.setAge(188);
b2.setUserName("小李子");
System.out.println("源对象:"+a1);
BeanUtils.copyProperties(a1,b1);
System.out.println("目标对象:"+b1);
}
// 源对象:B{userName='小红', age=99}
// 目标对象:Student{userName='小红', age=99, bornDate=null}
// 源对象:Student{userName='小李', age=18, bornDate=Wed Aug 10 20:45:37 CST 2022}
// 目标对象:B{userName='小李', age=18}
apache包中实践
/**
* 1、BeanUtils.copyProperties(a,b) 这个方法源和目标参数相反,a是目标对象,b是源对象
* 1.1 都是同一类的话,拷贝之后
*
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@Test
void t3() throws InvocationTargetException, IllegalAccessException {
// 1.1
System.out.println("1.1");
A b1 = new A();
b1.setAge(99);
b1.setUserName("小红");
A a = new A();
a.setBornDate(new Date());
a.setAge(18);
a.setUserName("小红1");
System.out.println("源对象:" + a);
org.apache.commons.beanutils.BeanUtils.copyProperties(b1, a);
System.out.println("目标对象:" + b1);
System.out.println("1.2");
// 1.2
A a2 = new A();
a2.setAge(99);
a2.setUserName("小红");
a2.setBornDate(new Date());
B b = new B();
b.setUserName("小红1");
b.setAge(98);
System.out.println("源对象:" + b);
org.apache.commons.beanutils.BeanUtils.copyProperties(a2, b);
System.out.println("目标对象:" + a2);
// 1.3
System.out.println("1.3");
A a3 = new A();
a3.setAge(99);
a3.setUserName("小红");
a3.setBornDate(new Date());
B b2 = new B();
b2.setUserName("小红1");
b2.setAge(98);
System.out.println("源对象:" + b2);
org.apache.commons.beanutils.BeanUtils.copyProperties(b2, a3);
System.out.println("目标对象:" + a3);
}
// 1.1
// 源对象:Student{userName='小红1', age=18, bornDate=Wed Aug 10 20:46:41 CST 2022}
// 目标对象:Student{userName='小红1', age=18, bornDate=Wed Aug 10 20:46:41 CST 2022}
// 1.2
// 源对象:B{userName='小红1', age=98}
// 目标对象:Student{userName='小红1', age=98, bornDate=Wed Aug 10 20:46:41 CST 2022}
// 1.3
// 源对象:B{userName='小红1', age=98}
// 目标对象:Student{userName='小红', age=99, bornDate=Wed Aug 10 20:46:41 CST 2022}
//
两种情况对比
org.apache.commons.beanutils.BeanUtils.copyProperties | org.springframework.beans.BeanUtils | |
---|---|---|
方法 | public static void copyProperties(Object dest, Object orig) | public static void copyProperties(Object source, Object target) |
参数说明 | dest:目标对象 orig:源对象 | source:源对象 target:目标对象 |
深拷贝和浅拷贝
浅拷贝
@Test
void t5() throws CloneNotSupportedException, ParseException {
C c = new C();
c.setAge(11);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmdd");
Date parse = simpleDateFormat.parse("20220810");
c.setBornDate(parse);
c.setUserName(UUID.randomUUID().toString().replace("-",""));
A a = new A();
a.setUserName("小红前");
c.setA(a);
C c1 = (C) c.clone();
System.out.println("+++++++++++++拷贝后+++++++++++++");
System.out.println(c1.getAge());
System.out.println(c1.getUserName());
System.out.println(c1.getBornDate());
System.out.println(c1.getA().getUserName());
System.out.println("+++++++++++++修改引用数据后+++++++++++++++++++++");
a.setUserName("小红后");
System.out.println(c1.getA().getUserName());
System.out.println(c.getA().getUserName());
// 11
// 4806df9d3068435fb64c8bcf0576de70
// Mon Jan 10 00:08:00 CST 2022
// 小红前
// +++++++++++++修改引用数据后+++++++++++++++++++++
// 小红前
// 小红前
//
}
结论分析: 两个引用c和c1指向不同的两个对象,但是两个引用c和c1中的两个a引用指向的是同一个对象,所以说明是浅拷贝。
深拷贝
深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。
@Test
void t6() throws CloneNotSupportedException, ParseException {
C c = new C();
c.setAge(11);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmdd");
Date parse = simpleDateFormat.parse("20220810");
c.setBornDate(parse);
c.setUserName(UUID.randomUUID().toString().replace("-",""));
A a = new A();
a.setUserName("小红前");
c.setA(a);
C c1 = (C) c.clone();
System.out.println("+++++++++++++拷贝后+++++++++++++");
System.out.println(c1.getAge());
System.out.println(c1.getUserName());
System.out.println(c1.getBornDate());
System.out.println(c1.getA().getUserName());
System.out.println("+++++++++++++修改引用数据后+++++++++++++++++++++");
a.setUserName("小红后");
System.out.println(c1.getA().getUserName());
System.out.println(c.getA().getUserName());
}
// 11
// 4806df9d3068435fb64c8bcf0576de70
// Mon Jan 10 00:08:00 CST 2022
// 小红前
// +++++++++++++修改引用数据后+++++++++++++++++++++
// 小红前
// 小红后
//
结果分析:两个引用c和c1指向不同对象,两个引用c和c1中两个A对象指向的是两个对象,但是对A对象的修改只能影响c对象,故而深拷贝。
本文含有隐藏内容,请 开通VIP 后查看