浅克隆
对于基本数据类型就是复制值,对于引用数据类型来说就是复制引用
深克隆
对于基本数据类型就是复制值,对于引用数据类型来说就是创建一个新的引用对象,然后将引用对象中的值复制到新的引用对象当中
浅拷贝测试案例
package clone;
import java.io.Serializable;
public class ShallowClone {
public static void main(String[] args) throws CloneNotSupportedException {
Bag bag = new Bag("大书包");
Student student = new Student("张三", 18, bag);
//对象进行浅拷贝
Student student1 = (Student)student.clone();
System.out.println("修改前:");
//输出被拷贝对象
System.out.println("被拷贝对象的值为:" + student);
//输出拷贝对象
System.out.println("拷贝对象的值为:" + student1);
//修改被拷贝对象属性中的基本数据类型
student.setName("李四");
student.setAge(33);
//修改被拷贝对象中的bag
student.getBag().setName("小书包");
System.out.println("修改后:");
//输出被拷贝对象
System.out.println("被拷贝对象的值为:" + student);
//输出拷贝对象
System.out.println("拷贝对象的值为:" + student1);
}
}
class Student implements Cloneable {
private String name;
private int age;
private Bag bag;
public Student(String name, int age, Bag bag) {
this.name = name;
this.age = age;
this.bag = bag;
}
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 Bag getBag() {
return bag;
}
public void setBag(Bag bag) {
this.bag = bag;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", bag=" + bag.getName() +
'}';
}
}
class Bag implements Cloneable, Serializable {
String name;
public Bag(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试结果
深拷贝测试案例
保持其它代码不变,只需要修改clone函数代码
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Student stu = (Student)obj;
stu.bag = (Bag)this.bag.clone();
return obj;
}
测试结果
通过实现Serializable接口实现深克隆(这种方法比较简单)
package clone;
import java.io.*;
public class SerializableClone {
public static void main(String[] args) {
Student2 stu = new Student2("张三", 18, new Bag("大书包"));
//字节输出缓冲流
//byteArray:字节输入流
ByteArrayOutputStream ops = new ByteArrayOutputStream();
try {
//创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(ops);
//读取对象并写入缓冲流
oos.writeObject(stu);
oos.flush();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ops.toByteArray()));
Student2 stu2 = ((Student2) ois.readObject());
stu.getBag().setName("小书包");
System.out.println(stu2.getBag().getName());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Student2 implements Serializable {
private String name;
private int age;
private Bag bag;
public Student2(String name, int age, Bag bag) {
this.name = name;
this.age = age;
this.bag = bag;
}
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 Bag getBag() {
return bag;
}
public void setBag(Bag bag) {
this.bag = bag;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", bag=" + bag +
'}';
}
}
测试结果分析
1.浅拷贝:对象中的引用类型只进行了引用拷贝,所指向的是同一个对象,修改被拷贝对象中的引用类型的值,拷贝对象中的值也会发生改变
2.深拷贝:在拷贝对象中的引用类型时,我们先为引用类型创建一个新的对象,然后将内容复制一份到这个新对象中,然后新引用指向这个新对象,此时我们修改被拷贝对象的引用属性时,拷贝对象中的引用属性不会发生改变
3.特别注意:String类型是不可变的,修改后其实是创建了一个新的对象