java对象复制

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));


 

猜你喜欢

转载自blog.csdn.net/jc_benben/article/details/106407307