在java中,提供了两种实现深克隆的方法,一种是采用序列化的方式实现,另一种是采用依次克隆各个可变的引用类型域的方式实现,但是序列化的效率并不理想。下面通过简单的例子进行对比:

编写类worker,在类中定义了两个域,name和age。在构造方法中初始化这两个域。并提供了get()和set()方法用于获得和修改这两个域。重写了toString()方便对象的输出,重写了clone()方法使用父类的clone()方法实现深克隆:

	public class Worker implements Cloneable{
    private String name;
    private int age;

    public Worker(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Worker clone(){
        Worker worker = null;
        try {
            worker = (Worker)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return worker;
    }
}

编写Employee类,定义两个域,name和age,在构造方法中初始化这两个域,并提供get()和set()方法用于获得和修改这两个域,再重写toString()方法用于对象的输出,重写clone()方法使用序列化的方式实现深克隆:

public class Employee implements Cloneable,Serializable {
    private static final long serialVersionUID = 5139250832033069055L;
    private String name;
    private int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Employee clone(){
        Employee employee = null;
        // 使用序列化实现深克隆
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);//    将对象写入到字节数组中
            oos.close();          //    关闭流
        } catch (IOException e) {
            e.printStackTrace();
        }

        ByteArrayInputStream bas = new ByteArrayInputStream(bos.toByteArray());
        try {
            ObjectInputStream ois = new ObjectInputStream(bas);// 从字节数组中读取对象
            try {
                employee = (Employee)ois.readObject();
                ois.close();                // 关闭流
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return employee;
    }
}

编写测试类来进行测试下,并分别输出采用两种方式创建十万个对象所花费的时间,代码如下:

	@Test
	public void Test(){
        List<Employee> employeeList = new ArrayList<>();
        Employee employee = new Employee("章子怡",20);
        /***************使用序列化的方式实现克隆*****************/
       System.out.println( "序列化 开始时间 ==> " +LocalTime.now());
        for (int i = 0; i < 100000; i++) {
            employeeList.add(employee.clone());
        }
        System.out.println( "序列化 结束时间 ==> " +LocalTime.now());

        List<Worker> workerList = new ArrayList<>();
        Worker worker = new Worker("汪峰",25);
        /***************使用复制域的方式实现克隆*****************/
        System.out.println( "复制域 开始时间 ==> " +LocalTime.now());
        for (int i = 0; i < 100000; i++) {
            workerList.add(worker.clone());
        }
    System.out.println( "复制域 结束时间 ==> " +LocalTime.now());
}

结果如下图:
有两种方式可以实现深克隆,其效率如何?
总结:
通过截图可以看出:

通过序列化的方式花费的时间是:
序列化 开始时间 ==> 15:28:19.095
序列化 结束时间 ==> 15:28:21.848

通过复制域的方式花费的时间是:
复制域 开始时间 ==> 15:28:21.849
复制域 结束时间 ==> 15:28:21.857

使用序列化的方式效率很低

相关文章:

  • 2021-10-15
  • 2022-12-23
  • 2022-12-23
  • 2021-10-03
  • 2022-12-23
  • 2022-12-23
  • 2021-12-23
  • 2021-12-19
猜你喜欢
  • 2021-11-23
  • 2021-08-14
  • 2021-08-08
  • 2021-12-23
  • 2021-07-10
  • 2021-12-01
相关资源
相似解决方案