浅拷贝:
package algorithm;
import java.util.ArrayList;
public class ShallowCopy implements Cloneable{
private String name;
private ArrayList<String> list = new ArrayList<String>();
public void printName(){
System.out.println(this.name);
}
public void setName(String name) {
this.name = name;
}
public void addListValue(String value){
this.list.add(value);
}
public void printlnList() {
System.out.println(this.list);
}
public ShallowCopy() {
System.out.println("shallow copy test");
}
/**
*
* 浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),
* 而不拷贝对象包含的引用指向的对象。深拷贝不仅拷贝对象本身,
* 而且拷贝对象包含的引用指向的所有对象。
*
*/
@Override
protected ShallowCopy clone() throws CloneNotSupportedException {
return (ShallowCopy) super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
ShallowCopy shallow = new ShallowCopy();
shallow.setName("yhx");
shallow.addListValue("Java");
shallow.printName();
shallow.printlnList();
ShallowCopy shallowCopy = shallow.clone(); // 克隆
// 打印出两个对象的地址
System.out.println(shallow);
System.out.println(shallowCopy);
shallowCopy.addListValue("Python");
shallowCopy.printlnList();
shallowCopy.printName();
shallowCopy.setName("hello");
shallow.printName(); // 输出 yhx
shallowCopy.printName();
shallow.printlnList(); // // 输出 Java,Python
/**
* 从结果中我们可以看到
拷贝时候虽然创建了新的对象,但是并没有调用构造方法
对象中的引用对象并没有拷贝,引用的地址还是和原对象一致
基本类型或者 String 默认会拷贝
像这种只拷贝了对象本身,而对象中引用数据类型没有被拷贝的拷贝方式,叫做浅拷贝。
浅拷贝往往存在一定的风险,因为引用对象的地址拷贝前后一致,所以对象的值很容易被更改,不安全。
*/
}
}
深拷贝:
①:
package algorithm;
import java.util.ArrayList;
public class DeepCopy implements Cloneable{
private String name;
private ArrayList<String> list = new ArrayList<>();
public void printlnName() {
System.out.println(this.name);
}
public void setName(String name) {
this.name = name;
}
public void addListValue(String value) {
this.list.add(value);
}
public void printlnList() {
System.out.println(this.list);
}
public DeepCopy() {
System.out.println("deep copy test");
}
@Override
protected DeepCopy clone() throws CloneNotSupportedException {
DeepCopy clone = (DeepCopy) super.clone();
clone.list = (ArrayList<String>) this.list.clone();
return clone;
}
public static void main(String[] args) throws CloneNotSupportedException {
DeepCopy deep = new DeepCopy();
deep.setName("yhx");
deep.addListValue("Java");
deep.printlnName();
deep.printlnList();
DeepCopy deepCopy = deep.clone(); // 克隆
// 打印出两个对象的地址
System.out.println(deep);
System.out.println(deepCopy);
deepCopy.printlnList();
deepCopy.addListValue("Python");
deepCopy.printlnList();
deepCopy.printlnName();
deepCopy.setName("hello");
deep.printlnName();
deep.printlnList();
//如果字段上有 final 修饰,就不能实现 clone 方法了,因为 final 变量不能再次被赋值。
}
}
②串行化深拷贝:
package algorithm;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
public class DeepCopyBySeriablizable{
//串行化很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。
public static void main(String[] args)
throws OptionalDataException, ClassNotFoundException, IOException {
long t1 = System.currentTimeMillis();
Professor2 p = new Professor2("wangwu", 50);
Student2 s1 = new Student2("zhangsan", 18, p);
Student2 s2 = (Student2) s1.deepClone();
s2.p.name = "lisi";
s2.p.age = 30;
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。
System.out.println("name=" + s2.p.name + "," + "age=" + s2.p.age);
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
}
}
class Professor2 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
String name;
int age;
Professor2(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student2 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
String name;// 常量对象。
int age;
Professor2 p;// 学生1和学生2的引用值都是一样的。
Student2(String name, int age, Professor2 p) {
this.name = name;
this.age = age;
this.p = p;
}
public Object deepClone() throws IOException, OptionalDataException,
ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
}