淺複製和深複製: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);
}
}