浅拷贝
浅拷贝结果是:新对像中包含的引用对象和原对象中包含的引用对象是同一个东东, 改变其中任何一个所包含的引用对象, 另一个也会受到影响
深拷贝
深拷贝结果是:新对象与原对象是完全独立的, 改变其中任何一个所包含的引用对像, 另一个都不会受到影响
浅拷贝例子 Object中的clone默认是浅拷贝
1 实现cloneable接口,这是个标记接口
2 重写Object的clone方法,调用父类的clone方法
public class Student { private String name; // 姓名 private int age; // 年龄 private StringBuffer sex; // 性别 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public StringBuffer getSex() { return sex; } public void setSex(StringBuffer sex) { this.sex = sex; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]"; } }
public class School implements Cloneable { private String schoolName; // 学校名称 private int stuNums; // 学校人数 private Student stu; // 一个学生 public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public int getStuNums() { return stuNums; } public void setStuNums(int stuNums) { this.stuNums = stuNums; } public Student getStu() { return stu; } public void setStu(Student stu) { this.stu = stu; } @Override protected School clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return (School) super.clone(); } @Override public String toString() { return "School [schoolName=" + schoolName + ", stuNums=" + stuNums + ", stu=" + stu + "]"; } public static void main(String[] args) throws CloneNotSupportedException { School s1 = new School(); s1.setSchoolName("实验小学"); s1.setStuNums(100); Student stu1 = new Student(); stu1.setAge(20); stu1.setName("zhangsan"); stu1.setSex(new StringBuffer("男")); s1.setStu(stu1); System.out.println( "s1: " + s1 + " s1的hashcode:" + s1.hashCode() + " s1中stu1的hashcode:" + s1.getStu().hashCode()); School s2 = s1.clone(); // 调用重写的clone方法,clone出一个新的school---s2 System.out.println("s2: " + s2 + " s2的hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode()); } }
s1和s2是不同的对象,但是他们包含的学生是同一个对象
s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s1的hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s2的hashcode:2018699554 s2中stu1的hashcode:1829164700
深拷贝
1 学生类实现cloneable接口
2 学生类重写clone方法
3 修改学校类的clone方法
public class Student implements Cloneable { private String name; private int age; private StringBuffer sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public StringBuffer getSex() { return sex; } public void setSex(StringBuffer sex) { this.sex = sex; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]"; } @Override protected Student clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return (Student) super.clone(); } }
public class School implements Cloneable { private String schoolName; // 学校名称 private int stuNums; // 学校人数 private Student stu; // 一个学生 public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public int getStuNums() { return stuNums; } public void setStuNums(int stuNums) { this.stuNums = stuNums; } public Student getStu() { return stu; } public void setStu(Student stu) { this.stu = stu; } @Override protected School clone() throws CloneNotSupportedException { School s = null; s = (School) super.clone(); s.stu = stu.clone(); return s; } @Override public String toString() { return "School [schoolName=" + schoolName + ", stuNums=" + stuNums + ", stu=" + stu + "]"; } public static void main(String[] args) throws CloneNotSupportedException { School s1 = new School(); s1.setSchoolName("实验小学"); s1.setStuNums(100); Student stu1 = new Student(); stu1.setAge(20); stu1.setName("zhangsan"); stu1.setSex(new StringBuffer("男")); s1.setStu(stu1); System.out.println("s1: " + s1 + " s1的hashcode:" + s1.hashCode() + " s1中stu1的hashcode:" + s1.getStu().hashCode()); School s2 = s1.clone(); // 调用重写的clone方法,clone出一个新的school---s2 System.out.println("s2: " + s2 + " s2的hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode()); // 修改s2中的值,看看是否会对s1中的值造成影响 s2.setSchoolName("希望小学"); s2.setStuNums(200); Student stu2 = s2.getStu(); stu2.setAge(30); stu2.setName("lisi"); stu2.setSex(stu2.getSex().append("6666666")); s2.setStu(stu2); // 再次打印两个school,查看结果 System.out.println("-------------------------------------------------------------------------"); System.out.println("s1: " + s1 + " hashcode:" + s1.hashCode() + " s1中stu1的hashcode:" + s1.getStu().hashCode()); System.out.println("s2: " + s2 + " hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode()); } }
s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s1的hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s2的hashcode:2018699554 s2中stu1的hashcode:1311053135
-------------------------------------------------------------------------
s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男6666666]] hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=希望小学, stuNums=200, stu=Student [name=lisi, age=30, sex=男6666666]] hashcode:2018699554 s2中stu1的hashcode:1311053135
可以修改s2中的性别,s1的也发生了改变,原因在于sex的类型是Stringbuffer,属于引用类型,在clone的时候将StringBuffer对象的地址传递了过去
这种情况应该怎么解决呢?
修改学生类的clone方法,设置sex时创建一个新的StringBuffer对象