Java之深浅拷贝
基本类型:拷贝数据的值
其他类型:拷贝地址的引用,拷贝出的新对象与原对象共享实例变量,不受访问权限影响
String类型:拷贝的也是一个引用,但其内容存储在字符串池中,修改时会重新生成新的字符串,原有字符串内容是保持不变的(String是不可变的),等同于基本类型。
浅拷贝
浅拷贝就是直接使用"="给基本类型赋值(即使拷贝引用)
List<String> srcList = new ArrayList<>();
srcList.add("android");
List<String> cpyList = srcList;
srcList.add("ios");
输出这两个list,srcList和cpyList都有android,ios两项。
深拷贝
深拷贝就是将所有属性均拷贝到另外一个对象中,将其中任何一个对象的任何一个属性发生变化时,另外一个对象不受任何影响。
List<String> srcList = new ArrayList<>();
srcList.add("android");
List<String> cpyList = new ArrayList<>(srcList);
srcList.add("ios");
输出这两个list,srcList有android,ios两项,而cpyList只有android一项。
clone方法实现拷贝
每个对象都是继承于Object类的,Object类提供了clone方法,通过实现Cloneable接口可以使该具有拷贝的能力,拷贝的操作是在内存中进行中,所以性能会比直接构造对象要快速很多。
public class Student implements Cloneable {
private String name;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
protected Student clone() {
Student s = null;
try {
s = (Student) super.clone();
s.setTeacher(s.getTeacher());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return s;
}
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Yao");
s1.setTeacher(new Teacher("Kobe"));
Student s2 = s1.clone();
s2.setName("Yi");
s2.getTeacher().setName("Jordan");
System.out.println(s1.getName() + "'s teacher is "
+ s1.getTeacher().getName());
System.out.println(s2.getName() + "'s teacher is "
+ s2.getTeacher().getName());
}
}
class Teacher {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher(String name) {
super();
this.name = name;
}
}
输出:
Yao's teacher is Jordan
Yi's teacher is Jordan
这里关于teacher的拷贝是通过"="号来操作的,仅仅实现了浅拷贝。
@Override
protected Student clone() {
Student s = null;
try {
s = (Student) super.clone();
s.setTeacher(new Teacher(s.getTeacher().getName()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return s;
}
将Student类的clone方法改成这样即可实现深拷贝。
输出:
Yao's teacher is Kobe
Yi's teacher is Jordan
通过对象序列化,使用writeObject和readObject也可以实现对象的深拷贝。