Detailed explanation of java deep copy and shallow copy (clone of method rewrite using serialization to achieve real deep copy)
- 2021-07-10 19:48:38
- OfStack
1. Serialization implementation
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object){
T cloneObj = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(object);
obs.close();
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
cloneObj = (T) ois.readObject();
}catch (Exception e){
e.printStackTrace();
}
return cloneObj;
}
}
2. Master code
public class TestString {
public static void main(String[] args) {
TestString test = new TestString();
System.out.println("------- Shallow copy ---------");
test.qianCopyTest();
System.out.println();
System.out.println("-------- Use clone Deep copy --------");
test.defaultCloneTest();
System.out.println();
System.out.println("-------- Implementing a copy of an object using serialization --------");
test.streamClonrTest();
System.out.println("-------- Time-consuming comparison --------");
System.out.println(" Time consuming 1 : "+ test.qianCopyCost());
System.out.println(" Time consuming 2 : "+ test.CloneCopyCost());
System.out.println(" Time consuming 3 : "+ test.StreamCopyCost());
}
/* Shallow copy */
private void qianCopyTest() {
String s = "cd";
change(s);
System.out.println(s);
System.out.println("----------------");
String b = new String("cd");
change(b);
System.out.println(b);
System.out.println("----------------");
int me = 1;
change(me);
System.out.println(me);
System.out.println("----------------");
Person person = new Person(" I ", 13,new Email(" I "));
change(person);
System.out.println(person.toString());
}
/* Use the default clone Method, need Person Realization Cloneable Interface */
private void defaultCloneTest(){
Person person = new Person(" I ", 13,new Email(" I "));
Person person1 = person.clone();
Person person2 = person.clone();
System.out.println("person : " "+person+" " ");
System.out.println("person1 : " "+person1+" " ");
System.out.println("person2 : " "+person2+" " ");
// Change 1 One will touch everything! ! This is to use the default clone Disadvantages of the method
/* The clone() The method is to use the Object Class clone() Method, but the method exists 1 It does not copy all the attributes of the object, but selectively copies them. The basic rules are as follows:
1 , Basic type
If the variable is of basic type, copy its value, such as int , float Wait.
2 , Object
If the variable is 1 Instance object, copy its address reference, that is to say, the new object and the original object are common to the instance variable.
3 , String String
If the variable is String String, its address reference is copied. But when modified, it is regenerated from the string pool 1 A new string, and the original Purple Capital object remains unchanged. */
person.getEmail().setContent(" You ");
System.out.println(" After person : " "+person+" " ");
System.out.println(" After person1 : " "+person1+" " ");
System.out.println(" After person2 : " "+person2+" " ");
}
/* Using serialization to implement a copy of an object requires that both the object and other objects in the object implement Serializable Interface */
private void streamClonrTest(){
Person person = new Person(" I ", 13,new Email(" I "));
Person person1 = CloneUtils.clone(person);
Person person2 = CloneUtils.clone(person);
System.out.println("person : " "+person+" " ");
System.out.println("person1 : " "+person1+" " ");
System.out.println("person2 : " "+person2+" " ");
person.getEmail().setContent(" You ");
System.out.println(" After person : " "+person+" " ");
System.out.println(" After person1 : " "+person1+" " ");
System.out.println(" After person2 : " "+person2+" " ");
}
private static void change(String x) {
x = "ab";
}
private static void change(int x) {
x = 2;
}
private static void change(Person x) {
x = new Person(" You ", 20, new Email(" You "));
}
private long qianCopyCost(){
long start = System.currentTimeMillis();
Person person = new Person(" I ", 13,new Email(" I "));
List<Person> list = new ArrayList<>();
for(int i = 0;i<=10000;i++){
list.add(new Person(" You ", 20, new Email(" You ")));
}
return System.currentTimeMillis()-start;
}
private long CloneCopyCost(){
long start = System.currentTimeMillis();
Person person = new Person(" I ", 13,new Email(" I "));
List<Person> list = new ArrayList<>();
for(int i = 0;i<=10000;i++){
list.add(person.clone());
}
return System.currentTimeMillis()-start;
}
private long StreamCopyCost(){
long start = System.currentTimeMillis();
Person person = new Person(" I ", 13,new Email(" I "));
List<Person> list = new ArrayList<>();
for(int i = 0;i<=10000;i++){
list.add(CloneUtils.clone(person));
}
return System.currentTimeMillis()-start;
}
}
class Person implements Serializable, Cloneable {
private static final long serialVersionUID = -8584225043397465132L;
private String name;
private int age;
public void setEmail(Email email) {
this.email = email;
}
private Email email;
public Email getEmail() {
return email;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age, Email email) {
this.name = name;
this.age = age;
this.email = email;
}
@Override
public String toString() {
return "name : " + name + " | age : " + age +" | content : "+email.getContent();
}
@Override
protected Person clone() {
Person person = null;
try {
person = (Person) super.clone();
/* If you add the following 1 Row "Use clone Deep copy " It won't change 1 Everything else has changed */
person.setEmail(new Email(person.getEmail().getContent()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
}
class Email implements Serializable {
private static final long serialVersionUID = 1426052929769365539L;
private String content;
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public Email(String content) {
this.content = content;
}
}
Tested for 1 time:
Output:
--Shallow copy--
cd
cd
1
name: I age: 13 content: I
----Using clone deep copy----
person: "name: I age: 13 content: I"
person1: "name: I age: 13 content: I"
person2: "name: I age: 13 content: I"
After person: "name: I age: 13 content: You"
After person1: "name: I age: 13 content: I"
After person2: "name: I age: 13 content: I"
-----Using serialization to implement a copy of an object-----
person: "name: I age: 13 content: I"
person1: "name: I age: 13 content: I"
person2: "name: I age: 13 content: I"
After person: "name: I age: 13 content: You"
After person1: "name: I age: 13 content: I"
After person2: "name: I age: 13 content: I"
--Time-consuming comparison--
It takes 1: 2
It takes 2: 1
It takes 3: 338