Object copying is basically a rigid requirement when we write code every day, and we often encounter it, but many people are busy writing business every day, ignoring some details and understanding. Sometimes, once there is a problem in this area, it is not easy to troubleshoot Up.
So this article sorts out.
Note: This article has been included in the Github open source project: github.com/hansonwang99/JavaCollection , which contains detailed self-learning programming learning routes, interview questions and interviews , programming materials and series of technical articles, etc. The resources are continuously updated...
Value type vs reference type
The distinction between these two concepts is very important for the understanding of deep and shallow copy problems.
As the title of the second chapter of the Java
Bible " Java
Programming Thoughts" says, Java
everything can be regarded as an object, so Java
the world that comes into it, such as arrays, classes Class
, enumerations Enum
, Integer
wrapper classes, etc., are typical reference types;
However Java
, language-level basic data types, such as int
these basic types, are generally operated by value transfer, so they are sometimes called value types.
In order to facilitate the following descriptions and examples, we first define two categories: Student
and Major
, which represent "students" and "professionals" respectively. The two are inclusive relationships:
// 学生的所学专业
public class Major {
private String majorName; // 专业名称
private long majorId; // 专业代号
// ... 其他省略 ...
}
// 学生
public class Student {
private String name; // 姓名
private int age; // 年龄
private Major major; // 所学专业
// ... 其他省略 ...
}
Assignment vs. shallow copy vs. deep copy
Object assignment
Assignment is the most common operation in the daily programming process, the simplest such as:
Student codeSheep = new Student();
Student codePig = codeSheep;
Strictly speaking, this cannot be regarded as an object copy, because the copy is only the reference relationship, and does not generate a new actual object:
Shallow copy
Shallow copy is a type of object cloning, and its important characteristics are reflected in the word "shallow" .
For example, we try to studen1
copy through examples. student2
If it is a shallow copy, the rough model can be shown as follows:
Obviously, the value type field will be copied, and the reference type field will only copy the reference address, and the actual object space pointed to by the reference address is actually only one copy.
A picture is better than the preface, I think the above picture has been very clear.
Deep copy
Deep copy is compared to the shallow copy shown above, except that the value type field will be copied, and the object pointed to by the reference type field will also be created in memory , just like this:
The principle is very clear, let's take a look at the specific code implementation.
Shallow copy code implementation
In the above example, I want to get it by student1
copying student2
. The typical implementation of shallow copy is: let the class of the copied object implement the Cloneable
interface and rewrite the clone()
method.
Take the above Student
class copy as an example:
public class Student implements Cloneable {
private String name; // 姓名
private int age; // 年龄
private Major major; // 所学专业
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
// ... 其他省略 ...
}
Then we write a test code, and you will know after a try:
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Major m = new Major("计算机科学与技术",666666);
Student student1 = new Student( "CodeSheep", 18, m );
// 由 student1 拷贝得到 student2
Student student2 = (Student) student1.clone();
System.out.println( student1 == student2 );
System.out.println( student1 );
System.out.println( student2 );
System.out.println( "\n" );
// 修改student1的值类型字段
student1.setAge( 35 );
// 修改student1的引用类型字段
m.setMajorName( "电子信息工程" );
m.setMajorId( 888888 );
System.out.println( student1 );
System.out.println( student2 );
}
}
Run and get the following results:
It can be seen from the results:
-
student1==student2
Printing false, describedclone()
approach does cloned a new object; -
Modifying the value type field does not affect the new cloned object, which is in line with expectations; -
Modify the student1
referenced objects inside, clonestudent2
also been affected, an internal or associated together
Deep copy code implementation
Deep traversal copy
Although the clone()
method can complete the copy work of the object, note: the clone()
method defaults to the shallow copy behavior, just like the example above. To achieve deep copy for an override clone()
depth traversing the copy-implemented method referenced object, blanket search.
So for the above example, if you want to implement deep copy, you first need to Major
transform the deeper reference class to implement the Cloneable
interface and rewrite the clone()
method:
public class Major implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// ... 其他省略 ...
}
Secondly, we also need to rewrite the method in the top-level calling class clone
to call the clone()
method of the reference type field to achieve deep copy, which corresponds to the Student
class in this article :
public class Student implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.major = (Major) major.clone(); // 重要!!!
return student;
}
// ... 其他省略 ...
}
At this time, the above test case is unchanged, and the result can be obtained by running:
Obviously, at this time student1
and the student2
two objects are completely independent, free from mutual interference.
Use deserialization to achieve deep copy
I remember that in the previous article "Serialization/Deserialization, I have to bear with you for a long time", I have sorted out and summarized the knowledge points of "serialization and deserialization" in detail.
Using deserialization technology, we can also deep copy from one object to another copied object, and this product is surprisingly effective in solving the problem of deep copying of multi-layer nesting dolls.
So let's modify the Student
class here and let its clone()
method generate a deep copy of the original object through serialization and deserialization:
public class Student implements Serializable {
private String name; // 姓名
private int age; // 年龄
private Major major; // 所学专业
public Student clone() {
try {
// 将对象本身序列化到字节流
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream =
new ObjectOutputStream( byteArrayOutputStream );
objectOutputStream.writeObject( this );
// 再将字节流通过反序列化方式得到对象副本
ObjectInputStream objectInputStream =
new ObjectInputStream( new ByteArrayInputStream( byteArrayOutputStream.toByteArray() ) );
return (Student) objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
// ... 其他省略 ...
}
Of course, in this case, the referenced subclass (such as the Major
class here ) must also be serializable, that is, it implements the Serializable
interface:
public class Major implements Serializable {
// ... 其他省略 ...
}
At this time, the test case is completely unchanged. If you run it directly, you can also get the following results:
Obviously, at this time student1
, the student2
two objects are completely independent, without mutual interference, and the deep copy is completed.
postscript
Okay, let's talk about the issue of "deep copy" and "shallow copy" this time. I thought that this article would be finished soon, and as a result, I pulled out so many things, but after sorting out and connecting in this way, I still feel a lot clearer.
That's it, see you in the next article.
Note: This article has been included in the Github open source project: github.com/hansonwang99/JavaCollection , which contains detailed self-learning programming learning routes, interview questions and interviews , programming materials and series of technical articles, etc. The resources are continuously updated...
Make small but daily progress
Slower can be faster