引用拷贝,只是单纯的将一个对象赋值给另一个对象,两个对象的引用地址完全一样。
举例:
Teacher teacher = new Teacher("Tom",26);
Teacher otherteacher = teacher;
System.out.println(teacher);
System.out.println(otherteacher);
输出结果:
blog.Teacher@355da254
blog.Teacher@355da254
结果分析:
由输出结果可以看出,他们的地址值是相等的,那么它们其实是同一个对象。两个对象都指向同一个对象。都是new Teacher("Tom",26)。这就是引用拷贝。
对象拷贝,是指将对象完全复制,两个对象互不影响,引用地址也不同。并且分为浅拷贝和深拷贝。
举例:
Teacher teacher = new Teacher("Swift",26); Teacher otherteacher = (Teacher)teacher.clone(); System.out.println(teacher); System.out.println(otherteacher); 输出结果:
blog.Teacher@355da254
blog.Teacher@4dc63996
结果分析:
由输出结果可以看出,他们的地址是不同的,也就是两个对象都有自己的引用变量。
接下来就是 浅拷贝和深拷贝的区别
被复制对象的所有变量都含有与原来的对象相同的值,
而所有的对其他对象的引用仍然指向原来的对象。
即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象
浅拷贝示例:
package blog;
/** * Created by 白夜行 on 2017/5/8. */ public class ShallowCopy { public static void main(String[] args) throws CloneNotSupportedException { Teacher teacher = new Teacher(); teacher.setName("Delacey"); teacher.setAge(29);
Student2 student1 = new Student2(); student1.setName("Dream"); student1.setAge(18); student1.setTeacher(teacher);
Student2 student2 = (Student2) student1.clone(); System.out.println("拷贝后"); System.out.println(student2.getName()); System.out.println(student2.getAge()); System.out.println(student2.getTeacher().getName()); System.out.println(student2.getTeacher().getAge()); System.out.println("修改老师的信息后-------------");
// 修改老师的信息 teacher.setName("Jam"); System.out.println(student1.getTeacher().getName()); System.out.println(student2.getTeacher().getName()); }
}
class Teacher implements Cloneable { private String name; private int age;
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; }
}
class Student2 implements Cloneable { private String name; private int age; private Teacher teacher;
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 Teacher getTeacher() { return teacher; }
public void setTeacher(Teacher teacher) { this.teacher = teacher; }
@Override public Object clone() throws CloneNotSupportedException { Object object = super.clone(); return object; }
}
输出结果:
拷贝后
Dream 18
Delacey 29
修改老师的信息后-------------
Jam
Jam
结果分析:
虽然两个student对象是不一样的,但是student引用的teacher是同一个对象,这就是 浅拷贝
深拷贝:
深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍,深拷贝都需要对象实现接口(Cloneable或是Serializable)
深拷贝示例一:
package blog;
/** * Created by 白夜行 on 2017/5/8. */
public class DeepCopy { public static void main(String[] args) throws Exception { Teacher2 teacher = new Teacher2(); teacher.setName("Delacey"); teacher.setAge(29);
Student3 student1 = new Student3(); student1.setName("Dream"); student1.setAge(18); student1.setTeacher(teacher);
Student3 student2 = (Student3) student1.clone(); System.out.println("拷贝后"); System.out.println(student2.getName()); System.out.println(student2.getAge()); System.out.println(student2.getTeacher().getName()); System.out.println(student2.getTeacher().getAge()); System.out.println("修改老师的信息后-------------");
// 修改老师的信息 teacher.setName("Jam"); System.out.println(student1.getTeacher().getName()); System.out.println(student2.getTeacher().getName()); } }
class Teacher2 implements Cloneable { private String name; private int age;
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; }
@Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
}
class Student3 implements Cloneable { private String name; private int age; private Teacher2 teacher;
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 Teacher2 getTeacher() { return teacher; }
public void setTeacher(Teacher2 teacher) { this.teacher = teacher; }
@Override public Object clone() throws CloneNotSupportedException { // 浅复制时: // Object object = super.clone(); // return object;
// 改为深复制: Student3 student = (Student3) super.clone(); // 本来是浅复制,现在将Teacher对象复制一份并重新set进来 student.setTeacher((Teacher2) student.getTeacher().clone()); return student; }
}输出结果:
拷贝后
Dream 18
Delacey 29
修改老师的信息后-------------
Jam
Delacey
结果分析:
这次不论student还是引用的teacher都是单独的对象,完全不相同。这就是深拷贝
深拷贝示例二:
package blog;
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable;
/** * Created by 白夜行 on 2017/5/13. */ public class DeepCopyServiable { public static void main(String[] args) throws Exception { Teacher3 t = new Teacher3(); t.setName("Taylor"); t.setAge(28);
Student3 s1 = new Student3(); s1.setAge(20); s1.setName("blank space"); s1.setTeacher(t);
Student3 s2 = (Student3) s1.deepClone();
System.out.println("拷贝后:"); System.out.println(s2.getName()); System.out.println(s2.getAge()); System.out.println(s2.getTeacher().getName()); System.out.println(s2.getTeacher().getAge()); System.out.println("---------------------------");
t.setName("swift");
System.out.println("修改后:"); System.out.println(s1.getTeacher().getName()); System.out.println(s2.getTeacher().getName()); }
}
class Teacher3 implements Serializable { private String name; private int age;
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; }
}
class Student3 implements Serializable { private String name; private int age; private Teacher3 teacher;
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 Teacher3 getTeacher() { return teacher; }
public void setTeacher(Teacher3 teacher) { this.teacher = teacher; }
public Object deepClone() throws Exception { // 序列化 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject(); }
}输出结果:
拷贝后:
blank space 20
Taylor 28
---------------------------
修改后:
swift
Taylor
结果分析:
说明序列化的方式实现了对象的拷贝。
可以这么理解,我只是为了自己看起来方便些,重新排版了下。
我发现深拷贝浅拷贝 其实都是需要实现拷贝接口或是序列化接口,并在类中创建一个这样的拷贝方法。感觉对类进行了进一步的拓展。不过对于拷贝这种方法的使用,目前好像没有发现太多的使用场景。如果说得不对,请大家指出,谢谢~
以及的代码及文字都是转至下面这位的博客,感谢~ 作者:白夜行515 来源: 原文:https://blog.csdn.net/baiye_xing/article/details/71788741 版权声明:本文为博主原创文章,转载请附上博文链接!
