Java中对象快速复制的几种方式详解

 更新时间:2023年08月02日 09:24:58   作者:程序猿渣渣帅  
这篇文章主要介绍了Java中对象快速复制的几种方式详解,对象的克隆是指创建一个新的对象,且新的对象的状态与原始对象的状态相同,当对克隆的新对象进行修改时,不会影响原始对象的状态,需要的朋友可以参考下

浅拷贝、深度复制、BeanUtils.copyProperties()

对象的克隆是指创建一个新的对象,且新的对象的状态与原始对象的状态相同。当对克隆的新对象进行修改时,不会影响原始对象的状态。

注释:clone()是object类的protected 方法,只有类的对象自己可以克隆自己

因此,必须实现cloneable接口才可以使用obj.clone()方法,典型的方式,如下

//浅拷贝
class CloneClass implements Cloneable{ 
 public int a; 
 public Object clone(){ 
  CloneClass o = null; 
  try{ 
   o = (CloneClass)super.clone(); 
  }catch(CloneNotSupportedException e){ 
   e.printStackTrace(); 
  } 
  return o; 
 } 
}
//深度拷贝
class CloneClass implements Cloneable{ 
 public int a; 
  public Class1 t;
  public CloneClass (int a,Class1 t) {
        this.a = a;
        this.t = t;
  }
 public Object clone(){ 
  CloneClass o = null; 
  try{ 
   o = (CloneClass)super.clone(); 
      o.test = (Class1)t.clone();
  }catch(CloneNotSupportedException e){ 
   e.printStackTrace(); 
  } 
  return o; 
 } 
}
//Class1 也必须实现Cloneable接口
class Class1 implements Cloneable{ 
    public Object clone(){ 
       Class1 o = null; 
       try{ 
         o = (Class1 )super.clone(); 
       }catch(CloneNotSupportedException e){ 
         e.printStackTrace(); 
       } 
       return o; 
 } 
}

一、浅拷贝clone()

如果对象中的所有数据域都是数值或者基本类型,使用clone()即可满足需求,如:

Person p = new Person();
Person p1 = p.clone();

这样p和p1分别指向不同的对象。

二、深度拷贝

如果在对象中包含子对象的引用,拷贝的结果是使得两个域引用同一个对象,默认的拷贝是浅拷贝,没有拷贝包含在对象中的内部对象。

如果子对象是不可变的,如String,这没有什么问题;如果对象是可变的,必须重新定义clone方法;

三、序列化可克隆(深拷贝)

/*
 * 为克隆使用序列化,
 * 直接将对象序列化到输出流中,然后将其读回,这样产生的新对象是对现有对象的一个深拷贝
 * 在此过程中,不必将对象写出到文件,可以用ByteArrayOutPutStream将数据保存到字节数组中
 * 
 * 这个方法很灵巧,它通常会比显示地构建新对象并复制或克隆数据域的克隆方法慢得多
 */
public class SerialCloneTest
{  
   public static void main(String[] args)
   {  
      Employee harry = new Employee("Harry Hacker", 35000);
      // clone harry
      Employee harry2 = (Employee) harry.clone();
      System.out.println(harry==harry2);
      System.out.println(harry);
      System.out.println(harry2);
   }
}
/**
   A class whose clone method uses serialization.
*/
class SerialCloneable implements Cloneable, Serializable
{ 
	private static final long serialVersionUID = 1L;
	//深拷贝
   public Object clone()
   {  
      try
      {  
         // save the object to a byte array
    	 //将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
         ObjectOutputStream out = new ObjectOutputStream(bout);
         out.writeObject(this);
         out.close();
         // read a clone of the object from the byte array
         ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
         ObjectInputStream in = new ObjectInputStream(bin);
         Object ret = in.readObject();
         in.close();
         return ret;
      }  
      catch (Exception e)
      {  
         return null;
      }
   }
}
/**
   The familiar Employee class, redefined to extend the
   SerialCloneable class. 
*/
class Employee extends SerialCloneable
{  
	private static final long serialVersionUID = 1L;
    private String name;
    private double salary;
   public Employee(String n, double s)
   {  
      name = n;
      salary = s;
   }
   public String getName()
   {  
      return name;
   }
   public double getSalary()
   {  
      return salary;
   }
   public String toString()
   {  
      return getClass().getName()
         + "[name=" + name
         + ",salary=" + salary
         + "]";
   }
}

四、BeanUtils.copyProperties()

三个测试类

public class Person {
    private String name;
    private String sex;
    private int age;
    private Date birthday;
    private Dog dog;
    public Dog getDog() {
        return dog;
    }
    public void setDog(Dog dog) {
        this.dog = dog;
    }
    private Double high;
    public String getName() {
        return name;
    }
    public Double getHigh() {
        return high;
    }
    public void setHigh(Double high) {
        this.high = high;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", dog=" + dog +
                ", high=" + high +
                '}';
    }
}
public class Dog {
    public String dogName;
    public String getDogName() {
        return dogName;
    }
    public void setDogName(String dogName) {
        this.dogName = dogName;
    }
    @Override
    public String toString() {
        return "Dog{" +
                "dogName='" + dogName + '\'' +
                '}';
    }
}
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
public class BeanUtilTest {
    public static void main(String[] args) {
        Person per = new Person();
        Person per1 = new Person();
        per.setName("zhangsan");
        per.setSex("男");
        per.setAge(20);
        per.setBirthday(new Date());
        Dog dog = new Dog();
        dog.setDogName("1111111111111111");
        per.setDog(dog);
        try {
            BeanUtils.copyProperties(per1, per);
            Dog dog1 = per.getDog();
            dog1.setDogName("2222222222222222");
            per.setName("666666666666");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(per.toString());
        System.out.println(per1.toString());
    }
}

输出:

Person{name='666666666666', sex='男', age=20, birthday=Wed Jul 25 18:21:29 CST 2018, dog=Dog{dogName='2222222222222222'}, high=null}
Person{name='zhangsan', sex='男', age=20, birthday=Wed Jul 25 18:21:29 CST 2018, dog=Dog{dogName='2222222222222222'}, high=0.0}

总结:

1、针对对象中的一般字段可以实现复制对象和源对象各自修改互不影响(如person的name属性)

2、针对里面的引用对象,没有实现嵌套的拷贝(如Dog对象)

到此这篇关于Java中对象快速复制的几种方式详解的文章就介绍到这了,更多相关Java对象快速复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java正则表达式matcher.group()用法代码

    Java正则表达式matcher.group()用法代码

    这篇文章主要给大家介绍了关于Java正则表达式matcher.group()用法的相关资料,最近在做一个项目,需要使用matcher.group()方法匹配出需要的内容,文中给出了详细的代码示例,需要的朋友可以参考下
    2023-08-08
  • MyBatis处理CLOB/BLOB类型数据以及解决读取问题

    MyBatis处理CLOB/BLOB类型数据以及解决读取问题

    这篇文章主要介绍了MyBatis处理CLOB/BLOB类型数据以及解决读取问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Java仿文库的基本方法(openoffice+swftools+flexPaper)

    Java仿文库的基本方法(openoffice+swftools+flexPaper)

    这篇文章主要为大家详细介绍了Java仿文库的基本方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Java实现抽奖算法的示例代码

    Java实现抽奖算法的示例代码

    这篇文章主要为大家详细介绍了如何利用Java语言实现抽奖算法,文中的示例代码讲解详细,对我们学习Java有一定帮助,需要的可以参考一下
    2022-04-04
  • java实现动态验证码

    java实现动态验证码

    这篇文章主要为大家详细介绍了java实现动态验证码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • 在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

    在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

    本文介绍了在Java中使用ModelMapper库简化Shapefile属性转JavaBean的过程,对比了原始的set方法和构造方法,展示了如何使用ModelMapper进行动态属性映射,从而减少手动编写转换代码的工作量,通过示例代码,展示了如何使用GeoTools读取Shapefile属性并将其转换为JavaBean对象
    2025-02-02
  • 防止SpringMVC拦截器拦截js等静态资源文件的解决方法

    防止SpringMVC拦截器拦截js等静态资源文件的解决方法

    本篇文章主要介绍了防止SpringMVC拦截器拦截js等静态资源文件的解决方法,具有一定的参考价值,有兴趣的同学可以了解一下
    2017-09-09
  • java压缩文件与删除文件的示例代码

    java压缩文件与删除文件的示例代码

    这篇文章主要介绍了java压缩文件与删除文件的示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java使用ftp上传文件示例分享

    java使用ftp上传文件示例分享

    这篇文章主要介绍了java使用ftp上传文件示例,需要的朋友可以参考下
    2014-02-02
  • java随机字符串生成示例

    java随机字符串生成示例

    这篇文章主要介绍了java随机字符串生成示例,这个字符随机生成类可以生成多种组合的字符串,比如大+小字符+数字+符号,需要的朋友可以参考下
    2014-03-03

最新评论