What is cloning
cloning, as the name suggests, is to clone an object's information to generate a new object. Then someone must have asked, why clone when there is new? Because the properties of new objects are initialized values, while those of clone objects can save the existing state of the object. When we need to temporarily save the existing state of an object, we can use clone. If we use new, we also need to re assign values. When there are many properties, it will be cumbersome. And clone is a native method, which interacts with the underlying operating system and will be faster.
be careful:
- Person p = new Person; Person p1 = p; This is not an object clone. It just wants to copy the reference of the person object to p2. The two references point to the same object. In fact, they operate on the same object. What is cloned is a new object.
- The cloned class must implement the clonable interface. The interface has no method, which is equivalent to a capability, indicating that the class implementing the interface can be cloned. Then override the clone() method in the Object class
Classification of clones
cloning can be divided into two categories: shallow cloning and deep cloning.
Shallow cloning
shallow clone: if the attribute of the object is basic data type or String type, copy a copy to the cloned object; If it is a reference type, the address of the reference object is copied to the clone object.
public class Person implements Cloneable{ private int age; private String name; private Address address; //setter and getter omitted @Override public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); // Directly call the clone() method of the parent class without any processing } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + ", address=" + address + '}'; } }
public class ShallowCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person(); // person1 object person1.setAge(22); person1.setName("Zhang San"); Address address = new Address("Beijing"); // reference type person1.setAddress(address); Person person2 = person1.clone(); person2.getAddress().setName("Nanjing"); // Modify the name attribute of the Address object in person2 System.out.println(person1); // The name attribute of the Address object in person1 is also modified System.out.println(person2); System.out.println(person1 == person2); // Judge whether the object from the clone is the same as the original object } }
The results are as follows:
It can be seen that when the attribute of an object is a basic type, a copy will be directly copied to the new object. If it is a reference type, the address of the reference type will be copied to the new object. Changing the value of the referenced object quoted by a reference type is equivalent to changing the two objects together.
Deep cloning
deep clone: if it is a basic data type, copy it directly to the cloned object; if it is a reference type, copy the referenced object to the cloned object.
package clone.bean; public class Person implements Cloneable{ private int age; private String name; private Address address; //setter and getter are omitted @Override public Person clone() throws CloneNotSupportedException { Person person = (Person) super.clone(); // clone object first person.address = (Address) address.clone(); // Deep clone: clone a copy of the referenced object return person; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + ", address=" + address + '}'; } }
public class DeepCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person(); // person1 object person1.setAge(22); person1.setName("Zhang San"); Address address = new Address("Beijing"); // reference type person1.setAddress(address); Person person2 = person1.clone(); person2.getAddress().setName("Nanjing"); // Modify the name attribute of the Address object in person2 System.out.println(person1); // Beijing System.out.println(person2); // Nanjing System.out.println(person1 == person2); } }
The results are as follows:
Deep cloning is successful, but if there are too many object reference types, rewriting the method becomes troublesome. Then you can use serialization to implement deep cloning and save the object in the stream.
public class DeepCloneTest2 { public static void main(String[] args) throws Exception { Person p1 = new Person(); p1.setAge(22); p1.setName("Zhang San"); Address address = new Address("Zhejiang"); p1.setAddress(address); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); // Read object into stream oos.writeObject(p1); // Write object ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());//Converts the data in the output stream to a byte array ObjectInputStream ois = new ObjectInputStream(bais);// read Person o = (Person) ois.readObject(); System.out.println(o); Person p2 = p1.clone(); p2.getAddress().setName("Shaanxi"); System.out.println(p2); ois.close(); bos.close(); } }