Object copy (5)

Object copy (5)

61. Why use cloning?

If you want to process an object, but also want to keep the original data for the next operation, you need to clone. The clone in the Java language is for the instance of the class.

62. How to implement object cloning?

There are two ways:

  • Implement the Cloneable interface and rewrite the clone() method in the Object class;
  • Realize the Serializable interface and realize cloning through the serialization and deserialization of objects, which can realize true deep cloning. The code is as follows:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MyUtil {
    
    

    private MyUtil() {
    
    
        throw new AssertionError();
    }

    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) throws Exception {
    
    
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();

        // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
    }
}

123456789101112131415161718192021222324252627

Here is the test code:

import java.io.Serializable;

/**
 * 人类
 * @author nnngu
 *
 */
class Person implements Serializable {
    
    
    private static final long serialVersionUID = -9102017020286042305L;

    private String name;    // 姓名
    private int age;        // 年龄
    private Car car;        // 座驾

    public Person(String name, int age, Car car) {
    
    
        this.name = name;
        this.age = age;
        this.car = car;
    }

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

    public Car getCar() {
    
    
        return car;
    }

    public void setCar(Car car) {
    
    
        this.car = car;
    }

    @Override
    public String toString() {
    
    
        return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }

}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
/**
 * 小汽车类
 * @author nnngu
 *
 */
class Car implements Serializable {
    
    
    private static final long serialVersionUID = -5713945027627603702L;

    private String brand;       // 品牌
    private int maxSpeed;       // 最高时速

    public Car(String brand, int maxSpeed) {
    
    
        this.brand = brand;
        this.maxSpeed = maxSpeed;
    }

    public String getBrand() {
    
    
        return brand;
    }

    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }

    public int getMaxSpeed() {
    
    
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
    
    
        this.maxSpeed = maxSpeed;
    }

    @Override
    public String toString() {
    
    
        return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";
    }

}

123456789101112131415161718192021222324252627282930313233343536373839
class CloneTest {
    
    

    public static void main(String[] args) {
    
    
        try {
    
    
            Person p1 = new Person("郭靖", 33, new Car("Benz", 300));
            Person p2 = MyUtil.clone(p1);   // 深度克隆
            p2.getCar().setBrand("BYD");
            // 修改克隆的Person对象p2关联的汽车对象的品牌属性
            // 原来的Person对象p1关联的汽车不会受到任何影响
            // 因为在克隆Person对象时其关联的汽车对象也被克隆了
            System.out.println(p1);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

1234567891011121314151617

Note: Cloning based on serialization and deserialization is not only deep cloning, but more importantly, through generic restriction, you can check whether the object to be cloned supports serialization. This check is done by the compiler, not at An exception is thrown at runtime. This solution is obviously better than using the clone method of the Object class to clone an object. It is always better to expose the problem at compile time than to leave the problem at runtime.

63. What is the difference between deep copy and shallow copy?

  • The shallow copy just copies the reference address of the object, and the two objects point to the same memory address, so if any value is modified, the other value will change accordingly. This is a shallow copy (for example: assign())
  • Deep copy is to copy the object and value, two objects modify any value of the other value will not change, this is deep copy (for example: JSON.parse() and JSON.stringify(), but this method cannot copy the function Types of)

Guess you like

Origin blog.csdn.net/xghchina/article/details/114708354