Java中的對象拷貝可以分為淺拷貝和深拷貝兩種類型。兩種拷貝方式的實現(xiàn)原理以及使用場景各不相同。
淺拷貝
淺拷貝是指在內(nèi)存中創(chuàng)建一個新的對象,對于基本類型的數(shù)據(jù)直接進(jìn)行值的復(fù)制,對于引用類型,僅僅是對對象地址的拷貝,新對象和原對象使用的是同一塊內(nèi)存區(qū)域。淺拷貝的效率高,但是當(dāng)原對象中的引用對象發(fā)生變化時,會對拷貝對象造成影響,因為拷貝對象和原對象變量對應(yīng)的引用指向同一個內(nèi)存地址。
public class ShallowCopy implements Cloneable{ public int[] arr; public ShallowCopy() { arr = new int[10]; for (int i = 0; i< arr.length; i++) { arr[i] = i; } } public Object clone() throws CloneNotSupportedException { return super.clone(); } } //調(diào)用clone方法 ShallowCopy obj1 = new ShallowCopy(); ShallowCopy obj2 = (ShallowCopy) obj1.clone(); //修改obj1引用的數(shù)組元素arr[0]的值 obj1.arr[0] = 100; //輸出數(shù)組元素arr[0]的值 System.out.println(obj1.arr[0]); System.out.println(obj2.arr[0]); //obj2.arr[0]的值也被改變了
深拷貝
深拷貝是指在內(nèi)存中對于所有的對象,都進(jìn)行拷貝,包括所有的引用對象。對于引用對象,會新建一個對象,并且復(fù)制其對應(yīng)的所有對象。深拷貝會消耗更多的時間和空間,但是拷貝后的對象與原對象互不影響,修改拷貝對象不會對原對象產(chǎn)生任何影響。
public class DeepCopy implements Serializable{ public int[] arr; public DeepCopy() { arr = new int[10]; for (int i = 0; i< arr.length; i++) { arr[i] = i; } } public Object deepClone() 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 ois.readObject(); } } //調(diào)用deepClone方法 DeepCopy obj1 = new DeepCopy(); DeepCopy obj2 = (DeepCopy) obj1.deepClone(); //修改obj1引用的數(shù)組元素arr[0]的值 obj1.arr[0] = 100; //輸出數(shù)組元素arr[0]的值 System.out.println(obj1.arr[0]); System.out.println(obj2.arr[0]); //obj2.arr[0]的值沒有改變
綜上所述,淺拷貝適用于對于簡單的數(shù)據(jù)類型進(jìn)行拷貝,對于復(fù)雜的數(shù)據(jù)類型可以采用深拷貝。需要注意的是,深拷貝需要對對象中的所有引用對象進(jìn)行處理才能保證拷貝后的對象完全獨立于原對象。