1. Direct assignment
/* Create class */ class Resume { private String name; //full name private String sex; //Gender private int age; //Age private String experience; //work experience public Resume(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setExperience(String experience) { this.experience = experience; } public String getExperience() { return experience; } public void displayResume() { System.out.println("full name:"+name+" Gender:"+sex+" Age:"+age); System.out.println("Work experience:"+experience); } } public class MainClass { public static void main(String[] args) { Resume zhangsan = new Resume("zhangsan","male",24); zhangsan.setExperience("2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Wait for code copy "); zhangsan.displayResume(); Resume zhangsan1 = zhangsan; zhangsan1.setExperience("2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Etc.); zhangsan.displayResume(); zhangsan1.displayResume(); } }
Program running results
full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Wait for code replication full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#etc. full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#etc.
In this program, a resume of Zhangsan is generated. Then I copied a resume zhangsan1. It can be seen that when the work experience in zhangsan1 changed, the work experience of Zhangsan also changed.
2. Shallow copy
/* Create a class to implement the Clone method */ class Resume implements Cloneable{ private String name; //full name private String sex; //Gender private int age; //Age private String experience; //work experience public Resume(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setExperience(String experience) { this.experience = experience; } public String getExperience() { return experience; } public void displayResume() { System.out.println("full name:"+name+" Gender:"+sex+" Age:"+age); System.out.println("Work experience:"+experience); } public Object clone() { try { return (Resume)super.clone(); } catch (Exception e) { e.printStackTrace(); return null; } } } public class MainClass { public static void main(String[] args) { Resume zhangsan = new Resume("zhangsan","male",24); zhangsan.setExperience("2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Etc. "); zhangsan.displayResume(); Resume zhangsan1 = (Resume)zhangsan.clone(); zhangsan1.setAge(23); zhangsan1.displayResume(); Resume zhangsan2 = (Resume)zhangsan.clone(); zhangsan2.setExperience("2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Etc. "); zhangsan2.displayResume(); zhangsan.displayResume(); } }
Program running results
full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Wait for code copy and paste full name: zhangsan Gender: male age:23 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Wait for code copy and paste full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Other code full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Studying at home and college, proficient in JAVA,C,C++,C#Wait for code copy and paste
class Experience { private String educationBackground; private String skills; public void setExperience(String educationBackground, String skills) { // TODO Auto-generated constructor stub this.educationBackground = educationBackground; this.skills = skills; } public String toString() { return educationBackground + skills; } } /* Create a class to implement the Clone method */ class Resume implements Cloneable{ private String name; //full name private String sex; //Gender private int age; //Age private Experience experience; //work experience public Resume(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; this.experience = new Experience(); } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public Experience getExperience() { return experience; } public void setExperience(String educationBackground, String skills) { experience.setExperience(educationBackground, skills); } public void displayResume() { System.out.println("full name:"+name+" Gender:"+sex+" Age:"+age); System.out.println("Work experience:"+experience.toString()); } public Object clone() { try { return (Resume)super.clone(); } catch (Exception e) { e.printStackTrace(); return null; } } } public class MainClass { public static void main(String[] args) { Resume zhangsan = new Resume("zhangsan","male",24); zhangsan.setExperience("2009-2013 Study at home and go to College","master JAVA,C,C++,C#Etc. "); zhangsan.displayResume(); Resume zhangsan2 = (Resume)zhangsan.clone(); zhangsan2.setExperience("2009-2013 Study at home and go to College","master JAVA,C,C++,C#Etc.); zhangsan2.displayResume(); zhangsan.displayResume(); zhangsan2.displayResume(); } }
Program running results:
full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Study at home and master college JAVA,C,C++,C#Wait for code copy and paste full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Study at home and master college JAVA,C,C++,C#etc. full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Study at home and master college JAVA,C,C++,C#etc. full name: zhangsan Gender: male age:24 Work experience: 2009-2013 Study at home and master college JAVA,C,C++,C#etc.
Let's take a look at the differences between the above two programs. The work Experience of the first program is a common member variable of the Resume class, that is, the value attribute. In the later program, work Experience is a class. Combined with the running results of the above program, we can understand that "if the field is a reference type, the reference is copied, but the referenced object is not copied. Therefore, the original object and its copy refer to the same object." in fact, the Experience classes in Zhangsan and zhangsan2 point to the same object! Either the Experience change in Zhangsan or the Experience change in zhangsan2 will affect the other.
3. Deep copy
In fact, the key to the problem lies in the clone() method. We know that the clone() method uses the clone() method of the Object class, but this method has a defect. It does not copy all the attributes of the Object, but selectively. The basic rules are as follows:
1. Basic type
If the variable is a basic type, copy its value, such as int, float, etc.
2. Object
If the variable is an instance object, copy its address reference, that is, the new object and the original object share the instance variable.
3. String string
If the variable is a String, copy its address reference. However, when modifying, it will regenerate a new String from the String pool, and the original purple capital object will remain unchanged.
Based on the above rules, we can easily find the problem. They share an object. If Zhang San modifies the content of the email, Li Si and Wang Wu will also modify it, so the above situation will occur. We can solve this problem. We just need to create an object in the clone() method, and then Zhang San references the object:
rotected Person clone() { Person person = null; try { person = (Person) super.clone(); person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent())); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; }
Therefore: shallow copy is only a simple copy mechanism provided by Java, which is not convenient for direct use.
There is still a problem with the above solution. If a large number of objects in our system are generated by copying, if we write a clone() method for each class, we will also need to make a deep copy and create a large number of objects. This project is very large. Here we can use serialization to copy objects.
How to use serialization to copy objects? It is easy to copy byte stream in memory. Write the parent object into a byte stream and read it from the byte stream. In this way, a new object can be created, and there is no reference sharing problem between the new object and the parent object, so as to truly realize the deep copy of the object.
public class CloneUtils { @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj){ T cloneObj = null; try { //Write byte stream ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(obj); obs.close(); //Allocate memory, write the original object, and generate a new object ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); //Returns the generated new object cloneObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } return cloneObj; } }
Objects using this tool class must implement the Serializable interface, otherwise there is no way to clone.
public class Person implements Serializable{ private static final long serialVersionUID = 2631590509760908280L; .................. //Remove clone() method } public class Email implements Serializable{ private static final long serialVersionUID = 1267293988171991494L; .................... }
Therefore, objects using this tool class can clone objects as long as they implement the Serializable interface, and there is no need to inherit the clonable interface to implement the clone() method.
public class Client { public static void main(String[] args) { //Write an email Email email = new Email("Please attend the meeting","Please contact today 12:30 Attend the meeting in conference room 2..."); Person person1 = new Person("Zhang San",email); Person person2 = CloneUtils.clone(person1); person2.setName("Li Si"); Person person3 = CloneUtils.clone(person1); person3.setName("Wang Wu"); person1.getEmail().setContent("Please contact today 12:00 Attend the meeting in conference room 2..."); System.out.println(person1.getName() + "The content of your email is:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "The content of your email is:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "The content of your email is:" + person3.getEmail().getContent()); } } ------------------- Output: The content of Zhang San's email is: please contact today 12:00 Attend the meeting in conference room 2... The content of Li Si's email is: please contact today 12:30 Attend the meeting in conference room 2... The content of Wang Wu's email is: please contact today 12:30 Attend the meeting in conference room 2...