序
Teacher teacher = new Teacher();
Teacher cloneTea = teacher;
cloneTea.setSalary(3000);
System.out.println("teacher: "+teacher);
System.out.println("cloneTea: "+cloneTea);
teacher: Teacher{salary=3000}
cloneTea: Teacher{salary=3000}
//Teacher cloneTea = teacher这句话只是将引用赋值
1. 浅克隆。
- 浅克隆:只复制基本类型的数据,引用类型的数据只复制了引用的地址
实现 : 被复制的类实现Clonenable接口,覆盖clone()方法
`java
public class Student implements Cloneable {//实现Cloneable接口
private Integer number;/* 重写clone方法(Object里clone方法是protect修饰的)
- */
@Override
public Object clone() {
Student student = null;
try {
} catch (CloneNotSupportedException e) {student = (Student) super.clone();
}e.printStackTrace();
return student;
}
}
- */
public static void main(String[] args) {
Student student1 = new Student();
student1.setNumber(200);
Student student2 = (Student) student1.clone();
System.out.println(student1==student2);
System.out.println("student1:" + student1);
System.out.println("student2:" + student2);
student2.setNumber(500);
System.out.println("student1:" + student1);
System.out.println("student2:" + student2);
}
```java
false//地址不一样了哦
student1:Student{number=200}
student2:Student{number=200}
student1:Student{number=200}
student2:Student{number=500}
但是如果Student类的属性是另外一个类的话,就会出现新的问题
public static void main(String[] args) {
Teacher teacher = new Teacher("武昌");
Student student1 = new Student();
student1.setTeacher(teacher);
Student student2 = (Student) student1.clone();
System.out.println(student1 == student2);
System.out.println("student1:" + student1);
System.out.println("student2:" + student2);
student2.getTeacher().setAddress("江夏");
System.out.println("student1:" + student1);
System.out.println("student2:" + student2);
}
false
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student1:Student{number=null, teacher=Teacher{salary=null, address='江夏'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='江夏'}}
可以看到两个address都变了
稍微修改一行代码
student2.setTeacher(new Teacher("汉口"));
false
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='汉口'}}
可以发现student1的address没变
显而易见,浅克隆中属性如果是一个类的话,那么复制的是这个类的地址
2. 深克隆
- 深克隆: 是在引用类型的类中也实现了clone,是clone的嵌套,复制后的对象与原对象之间完全不会影响。
- 实现 : 不仅需要将被复制的类实现Clonenable接口,覆盖clone()方法而且该类中的某个类型为类的属性也需要被复制的话那这个类也需要实现Clonenable接口,覆盖clone()方法;
- 如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。
3. 使用序列化的方式解决多层克隆
使用序列化也能完成深复制的功能:对象序列化后写入流中,此时也就不存在引用什么的概念了,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。
public class Test { public static void main(String[] args) throws Exception { Teacher teacher = new Teacher(); teacher.setAddress("西湖"); Teacher teacher1 = (Teacher) cloneObj(teacher); System.out.println(teacher==teacher1); System.out.println("teacher:"+teacher); System.out.println("teacher1:"+teacher1); } public static Object cloneObj(Teacher teacher) throws Exception { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(byteOut); objOut.writeObject(teacher); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream objIn = new ObjectInputStream(byteIn); return objIn.readObject(); } }false teacher:Teacher{salary=null, address='西湖'} teacher1:Teacher{salary=null, address='西湖'}