java中有时候需要复制对象,比如别人调用你,你最好不要修改人家的参数内容,
(1)将A对象的值分别通过set方法加入B对象中;
(2)通过重写java.lang.Object类中的方法clone();
(3)通过org.apache.commons中的工具类BeanUtils和PropertyUtils进行对象复制;
说明下,这里其实有两个实现,一个是apache一个是spring
org.apache.commons.beanutils.BeanUtils 和 org.springframework.beans.BeanUtils区别
区别:
Apache的beanuntils.copyProperties()在遇到int/long的null进行复制的时候会变成0
spring的beanuntils.copyProperties()就正常,两个的des目标对象和src源对象左右位置不一样
(4)通过序列化实现对象的复制
说明
1) geter、seter方法在对象中属性比较少时可以用,多的话麻烦
2)这里分为浅copy和深copy
浅copy步骤:
a)被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常),该接口为标记接口(不含任何方法)
b)覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象
举例:
public class User implements Cloneable{
String userName;
String userAddress;
Integer age;
@Override
public Object clone() {
User user = null;
try{
user = (User)super.clone(); //浅复制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return user;
}
public User(String userName, String userAddress, Integer age) {
this.userName = userName;
this.userAddress = userAddress;
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class Test {
public static void main(String args[]) {
User user1 = new User();
user1.setNumber(12345);
User user2 = (User)user1.clone();
}
}
深copy:
如果user类中的address也是一个类,这样浅复制只是复制了address变量的引用,并没有真正的开辟另一块空间。
为了达到真正的复制对象,而不是纯粹引用复制。需要将Address类也改为可复制化,并且修改clone方法即可,
class Address implements Cloneable {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
@Override
public Object clone() {
Address addr = null;
try{
addr = (Address)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return addr;
}
}
然后修改上面的user类
Address userAddress;
@Override
public Object clone() {
User user = null;
try{
user = (User)super.clone(); //浅复制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
user.userAddress = (Address)userAddress.clone(); //深度复制
return user;
}
4)工具类BeanUtils和PropertyUtils进行对象复制
User sourceUser = new User("zhangsan", "beijing", 28);
User targetUser = new User();
BeanUtils.copyProperties(sourceUser,targetUser);
copyProperties()方法作用与BeanUtils的同名方法十分相似,主要的区别在于BeanUtils提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而PropertyUtils不支持这个功能,但是速度会更快一些
5)、通过序列化实现对象的复制
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作
问题:
如果是集合复制会出现问题,这个需要用循环
List<User> source = new LinkedList<>();
List<User> target = new LinkedList<>();
User user1 = new User("zhangsan", "beijing", 10);
User user2 = new User("lisi", "beijing", 30);
source.add(user1);
source.add(user2);
int count = source.size();
Long start = System.nanoTime();
for (int i = 0; i < count; i++) {
User p = new User();
BeanUtils.copyProperties(source.get(i), p);
target.add(p);
}
System.out.println("BeanUtils.copyProperties" + (System.nanoTime() - start));