Wechat search “Java fish”, a knowledge point every day not bad
One knowledge point a day
What does cloneable interface do, shallow copy and deep copy?
(1) What is the use of cloneable interface
We all know that copying requires implementing the Cloneable interface and implementing the Clone () method in the class, but the amazing thing is that the clone() method is not in the Cloneable interface.
The Cloneable interface is an empty interface with no content in it
However, if the Cloneable interface is not implemented, it will cause the clone() method to report a CloneNotSupportException, so you can consider the Cloneable interface as a necessary element to implement the clone() method.
(2) What is deep copy and shallow copy
Sometimes during development, you will encounter the need to copy all member attributes of an existing object to another object. This is where the concept of copy comes in. We define the original object as A, and the copied object as B. If clone method is used only, you will find:
1. For the eight basic types, their values are copied and changes in B do not affect A.
2. If it is an object, the address reference is copied, that is, the newly copied object shares the instance variable with the original object, and is not restricted by access permissions. B’s change in this value affects A.
3. In the case of String strings, this is special. Although it is copied as a reference, when modified, it will generate a new String from the String pool, leaving the original String object unchanged.
The action of simply copying the reference address is a shallow copy.
In contrast, when copying an object does not simply copy the address reference, but creates a new object, this is called deep copy.
(3) shallow copy code simulation
Simulate the shallow copy process with code:
First, create two entity classes, student and teacher:
public class Teacher {
private int id;
private String name;
// omit the constructor, get, set, toString methods
}
Copy the code
Next comes the student, whose entity class needs to implement Clone
public class Student implements Cloneable {
private int id;
private String name;
private Teacher teacher;
// omit the constructor, get, set, toString methods
@Override
protected Object clone(a) throws CloneNotSupportedException {
return super.clone(); }}Copy the code
Let’s look at the effect of shallow copy
public static void main(String[] args) throws CloneNotSupportedException {
// Create a new student1
Student student1=new Student(1."javayz".new Teacher(1."teacher1"));
// Student2 clone from student1
Student student2= (Student) student1.clone();
// Change the base type int
student2.setId(2);
/ / modify the String
student2.setName("javayz2");
// Modify the object type teacher
Teacher teacher = student2.getTeacher();
teacher.setName("teacher2");
System.out.println(student1);
System.out.println(student2);
}
Copy the code
As you can see from the results, changing the base type and String type of the cloned object does not affect the original data, but because the same reference address is used, both are modified.
(4) deep copy code simulation
One method of deep copying is to make a deep copy of all the reference types in the copied object, and then layer by layer to make the reference address new rather than the same.
Modify the teacher object code above to implement the Clone method
public class Teacher implements Cloneable{
private int id;
private String name;
// omit the constructor, get, set, toString methods
@Override
protected Object clone(a) throws CloneNotSupportedException {
return super.clone(); }}Copy the code
Change the clone method of student
@Override
protected Object clone(a) throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.teacher= (Teacher) teacher.clone();
return student;
}
Copy the code
Then execute the same test code and discover that the two objects no longer affect each other.
The second approach is to implement deep copy with Serializable. This approach works by writing serialized objects to AN I/O stream and then retrieving them to implement deep copy. All classes involved in this approach must implement the Serializable interface
Create a new DeepStudent class
public class DeepStudent implements Serializable {
private static final long serialVersionUID=1L;
private int id;
private String name;
private Teacher teacher;
// omit the constructor, get, set, toString methods
public Object deepCopy(a){
try {
// Write the object to the IO stream
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
// Get the object from the IO stream
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null; }}Copy the code
Write a test method:
public static void main(String[] args) throws CloneNotSupportedException {
// Create a new student1
DeepStudent student1=new DeepStudent(1."javayz".new Teacher(1."teacher1"));
// Student2 clone from student1
DeepStudent student2= (DeepStudent) student1.deepCopy();
// Change the base type int
student2.setId(2);
/ / modify the String
student2.setName("javayz2");
// Modify the object type teacher
Teacher teacher = student2.getTeacher();
teacher.setName("teacher2");
System.out.println(student1);
System.out.println(student2);
}
Copy the code