浅克隆和深克隆

浅复制和深复制:java

钱复制:克隆对象(A1)的全部变量都含有与原对象(A)相同的值,对象内部的引用对象(B)仍然指向原来的对象(B),浅复制仅仅复制所考虑的对象,而不复制它所引用的对象this

深复制:克隆对象(A1)的全部变量都含有与原对象(A)相同的值,除去那些引用对象(B),那些引用对象(B)的变量将指向被复制过的新对象B1,而再也不是原有的那些被引用的对象(B),深复制把要复制对象spa

所引用的对象都复制一遍对象

Java中的clone方法接口

(1)clone方法将对象复制一份并返回给被调用者,clone方法知足:get

1.对任何的对象x,都有x.clone!=x  即克隆对象与原对象不是同一个对象it

2.对任何的对象x,都有x.clone.getClass == x.getClass  克隆对象与原对象类型同样io

3.若是对象x的equals方法定义恰当,那么x.clone.equals(x)应该成立class


(2)java中对象的克隆import

1.位了获取对象的一份拷贝,咱们能够利用Object的clone方法

2.在派生子类中定义克隆方法,名字随意,能够叫clone(),并声明为public

3.在派生类的克隆方法中,调用super.clone()

4.派生类实现cloneable接口

1. 浅复制案例:

public class Professer{

String name;

int age;

public Professer(String name,int age) {

this.name = name;

this.age = age;

}

}

public class Student implements Cloneable{

String name;

int age;

Professer p;

Student(String name,int age,Professer p){

this.name = name;

this.age = age;

this.p = p;

}

public Student clone2() throws CloneNotSupportedException{

Student s = (Student) super.clone();

/********/

//若是professer类不实现cloneable接口,并且不写克隆方法供下面调用(s.p = p.clone3()方法被注释掉),则生成的结果如p1.png

//说明:1.克隆对象与原对象中的变量值是同样的,引用对象指向的是同一个对象;2.修改克隆对象中的普通变量对原对象没有影响,但修改克隆对象中引用对象的值,原对象中引用对象的值也发生改变

//********上述这种复制方式为浅复制*******//

//若是professer类实现了cloneable接口,并且写了克隆方法供下面调用(s.p = p.clone3()存在),则生成结果如p2.png

//说明:1.克隆对象与原对象中的变量值是同样的,引用对象指向的不是同一个对象;2.修改克隆对象中的普通变量对原对象没有影响,同时修改克隆对象引用对象的值,原对象中引用对象的值没变,克隆对象

//中的引用对象和元对象中的引用对象不是一个东西

//********上述这种复制方式为深复制******//

//s.p =  p.clone3();

/*********/

return s;

}

public static void main(String[] args) throws CloneNotSupportedException {

Professer p3 = new Professer("王五", 50);

Student s1 = new Student("张三", 18, p3);

Student s2 = s1.clone2();

System.out.println("[v1]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v1]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

System.out.println();

s2.name = "李四";

s2.age = 20;

System.out.println("[v2]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v2]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

System.out.println();

s2.p.name = "赵六";

s2.p.age = 100;

System.out.println("[v3]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v3]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

}

}

总结:

(1).浅克隆中,克隆对象中普通变量和引用对象的值,都与原对象的值保持一致;

(2).浅克隆时,克隆对象和原对象不是同一个对象,但他们内部的【引用对象】指向的是同一个对象

(3).浅克隆时,修改普通变量,克隆对象和原对象互不影响,但修改引用对象时,二者引用对象的值同时改变


深克隆:

原对象A;

引用对象B;

克隆对象A1;

深复制的两种方式:

1. B实现cloneable接口,提供克隆方法,A实现cloneable接口,提供克隆方法的同时,调用B的克隆方法

2. 利用串行化来作深复制P:在Java里,深复制一个对象,经常能够先使对象实现serializabel接口,而后把对象写到一个流里,再从流里读出来,即可以重建对象;

=====>前提是要保证对象和对象内部全部引用到的对象都是可串行化的

案例1:

public class Professer implements Cloneable{

String name;

int age;

public Professer(String name,int age) {

this.name = name;

this.age = age;

}

public Professer clone3() throws CloneNotSupportedException{

return (Professer) super.clone();

}

}

public class Student implements Cloneable{

String name;

int age;

Professer p;

Student(String name,int age,Professer p){

this.name = name;

this.age = age;

this.p = p;

}

public Student clone2() throws CloneNotSupportedException{

Student s = (Student) super.clone();

/********/

//若是professer类不实现cloneable接口,并且不写克隆方法供下面调用(s.p = p.clone3()方法被注释掉),则生成的结果如p1.png

//说明:1.克隆对象与原对象中的变量值是同样的,引用对象指向的是同一个对象;2.修改克隆对象中的普通变量对原对象没有影响,但修改克隆对象中引用对象的值,原对象中引用对象的值也发生改变

//********上述这种复制方式为浅复制*******//

//若是professer类实现了cloneable接口,并且写了克隆方法供下面调用(s.p = p.clone3()存在),则生成结果如p2.png

//说明:1.克隆对象与原对象中的变量值是同样的,引用对象指向的不是同一个对象;2.修改克隆对象中的普通变量对原对象没有影响,同时修改克隆对象引用对象的值,原对象中引用对象的值没变,克隆对象

//中的引用对象和元对象中的引用对象不是一个东西

//********上述这种复制方式为深复制******//

s.p =  p.clone3();

/*********/

return s;

}

public static void main(String[] args) throws CloneNotSupportedException {

Professer p3 = new Professer("王五", 50);

Student s1 = new Student("张三", 18, p3);

Student s2 = s1.clone2();

System.out.println("[v1]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v1]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

System.out.println();

s2.name = "李四";

s2.age = 20;

System.out.println("[v2]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v2]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

System.out.println();

s2.p.name = "赵六";

s2.p.age = 100;

System.out.println("[v3]s1.name = " + s1.name + ";s1.age = " + s1.age + ";s1.p.name = " + s1.p.name + ";s1.p.age = " + s1.p.age);

System.out.println("[v3]s2.name = " + s2.name + ";s2.age = " + s2.age + ";s2.p.name = " + s2.p.name + ";s2.p.age = " + s2.p.age);

}

}

案例2:

import java.io.Serializable;

public class Teacher implements Serializable{

private static final long serialVersionUID = 1L;

String name;

int age;

Teacher(String name,int age){

this.name = name;

this.age = age;

}

}

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;


public class Student implements Serializable{

private static final long serialVersionUID = 1L;

String name;

int age;

Teacher t;

public Student(String name,int age,Teacher t){

this.name = name;

this.age = age;

this.t = t;

}

public Student deetClone() throws IOException, ClassNotFoundException{

ByteArrayOutputStream bos = new ByteArrayOutputStream();

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(this);

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());

ObjectInputStream ois = new ObjectInputStream(bis);

return (Student) ois.readObject();

}

public static void main(String[] args) throws ClassNotFoundException, IOException {

Teacher t = new Teacher("AAA",30);

Student s1 = new Student("A", 10, t);

Student s2 = s1.deetClone();

System.out.println("[v1]s1.name = " + s1.name + ";s1.age = " + s1.age + "; s1.t.name = " + s1.t.name + ";s1.t.age = " + s1.t.age);

System.out.println("[v1]s2.name = " + s2.name + ";s2.age = " + s2.age + "; s2.t.name = " + s2.t.name + ";s2.t.age = " + s2.t.age);

System.out.println();

s2.t.name = "BBB";

s2.t.age = 50;

System.out.println("[v1]s1.name = " + s1.name + ";s1.age = " + s1.age + "; s1.t.name = " + s1.t.name + ";s1.t.age = " + s1.t.age);

System.out.println("[v1]s2.name = " + s2.name + ";s2.age = " + s2.age + "; s2.t.name = " + s2.t.name + ";s2.t.age = " + s2.t.age);

}

}