java 中 的 deep copy 與 shallow copy
當我們檢視 Object 中的clone() 方法的API時發現有這樣一段話:‘......this method performs a "shallow copy" of this object, not a "deep copy" operation....’
事實確實這樣,是一個複雜物件該方式是無法實現clone的。 仔細看下會發現該方法 使用‘protected’修飾的,這樣造成的後果就是:對那些簡單地使用一下這個類的客戶程式設計師來說,他們不會預設地擁有這個方法;其次,我們不能利用指向基礎類的一個控制代碼來呼叫clone()(儘管那樣做在某些情況下特別有用,比如用多形性的方式克隆一系列物件)。
那麼我們如何實現深度copy呢??
上程式碼前先看看 ObjectOutputStream 的 writeObject(Object obj) 和
ObjectInputStream 的 readObject() 方法的API
方法writeObject(Object obj):
/**
* Write the specified object to the ObjectOutputStream. The class of the
* object, the signature of the class, and the values of the non-transient
* and non-static fields of the class and all of its supertypes are
* written. Default serialization for a class can be overridden using the
* writeObject and the readObject methods. Objects referenced by this
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*...............................
方法readObject():
Objects referenced by this object are read transitively so that a complete equivalent graph of objects is reconstructed by readObject.
程式碼還是最能說明問題的:
package com.test.clone;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int age;
private String name;
public Person(){};
public Person(int age,String name){
this.age=age;
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
public static void main(String[] args) {
Person person = new Person();
//person.clone();
}
}
-------------------------------------------------------------------------------------
package com.test.clone;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
public class PersonDeepCopyTest {
public static <T> void printList(List<T> list){
System.out.println("---begin---");
for(T t : list){
System.out.println(t);
}
System.out.println("---end---");
}
public static <T> void printArray(T[] array){
System.out.println("---begin---");
for(T t : array){
System.out.println(t);
}
System.out.println("---end---");
}
/**
* 深度copylist
* @param <T>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
@SuppressWarnings("unchecked")
List<T> dest = (List<T>) in.readObject();
return dest;
}
/**
*
* @param <G>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G> List<G> deep4Copy(List<G> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
List<G> dest = (List<G>) in.readObject();
return dest;
}
/**
* 深度copyMap
* @param <G>
* @param <E>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G,E> Map<G,E> deep4MapCopy(Map<G,E> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
Map<G,E> dest = (Map<G,E>) in.readObject();
return dest;
}
/**
* 深度copy Hashtable
* @param <G>
* @param <E>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G,E> Hashtable<G,E> deep4HashTableCopy(Hashtable<G,E> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
Hashtable<G,E> dest = (Hashtable<G,E>) in.readObject();
return dest;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> srcList=new ArrayList<Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcList.add(p1);
srcList.add(p2);
srcList.add(p3);
/* List<Person> destList=new ArrayList<Person>(srcList.size());
for(Person p : srcList){
destList.add(p); //無法實現深度copy
}
printList(destList);
srcList.get(0).setAge(100);
printList(destList);
printList(srcList);*/
/* List<Person> destList=new ArrayList<Person>();
destList.addAll(srcList); //無法實現深度copy
printList(destList);
srcList.get(0).setAge(100);
printList(destList);
printList(srcList);*/
List<Person> destList=deepCopy(srcList); //可實現List深度copy
printList(destList);
destList.get(0).setAge(100);
printList(destList);
printList(srcList);
/* Map<String,Person> srcMap=new HashMap<String,Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcMap.put(p1.getName(),p1);
srcMap.put(p2.getName(),p2);
srcMap.put(p3.getName(),p3);
Map<String, Person> destMap = deep4MapCopy(srcMap);//可實現Map深度copy
System.out.println(destMap);
destMap.get("abc").setAge(100);
System.out.println(destMap);
System.out.println(srcMap);*/
/* Hashtable<String,Person> srcHashTable=new Hashtable<String,Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcHashTable.put(p1.getName(),p1);
srcHashTable.put(p2.getName(),p2);
srcHashTable.put(p3.getName(),p3);
Map<String, Person> desthashtable = deep4HashTableCopy(srcHashTable);//可實現List深度copy
System.out.println(desthashtable);
desthashtable.get("abc").setAge(100);
System.out.println(desthashtable);
System.out.println(srcHashTable);*/
}
}
相關推薦
java 中 的 deep copy 與 shallow copy
當我們檢視 Object 中的clone() 方法的API時發現有這樣一段話:‘......this method performs a "shallow copy" of this object, not a "deep copy" operation....’ 事實確
Python中的淺複製(shallow copy)和深複製(deep copy)
近期雜事太多,部落格一直沒更新,9月最後一天了,總得寫點吧 今天記一下以前碰到過,最近又碰到的問題:python的深複製和淺複製 神奇的python中,copy竟然還有兩種,一深一淺(emm),來看看它們有什麼區別。 python值管理方式 這本質原因是pyt
deep copy and shallow copy
並不是 hal bject target vps www col att truct 鏈接A:淺拷貝就是成員數據之間的一一賦值:把值賦給一一賦給要拷貝的值。但是可能會有這樣的情況:對象還包含資源,這裏的資源可以值堆資源,或者一個文件。。當值拷貝的時候,兩個對象就有用共同的資
Java 中的寫時複製 (Copy on Write, COW)
Background 寫時複製 (Copy on Write, COW) 有時也叫 "隱式共享", 顧名思義, 就是讓所有需要使用資源 R 的使用者共享資源 R 的同一個副本, 當其中的某一個使用者要對資源 R 進行修改操作時, 先複製 R 的一個副本 R' , 再進行修改操作; Problem 在 J
Java 中執行CMD命令(copy/ping)
java實現一些cmd命令 最近在專案中需要用到一些cmd命令,於是利用java提供的Runtime.getRuntime().exec(cmd)方法執行,現對使用的一些命令做一下小結。: 執行copy 命令 執行ping命令 執行copy命令
淺copy 與 深copy
三種 發生 nbsp cnblogs 復制 end his code spa 1 import copy 2 names = ["zhangyang", ‘guyun‘, ‘xiangpeng‘, [‘jack‘,‘tom‘], ‘xuliangchen‘] 3 n
Java中字節與對象之間的轉換
ring str arr cti void too trac port ear 近期公司裏面用到了消息隊列,而正如我們知道的是消息隊列之間的是通過二進制形式的。以下就分享一下java中字節與對象之間的轉換。 主要是用到了ByteArrayOutputStream和Ob
java中的類與對象
共享 泛化 不能 變量聲明 eas diag 特征 類變量 set 面向對象編程主要有三個特征:封裝、繼承和多態。 封裝 一個簡單的問題 一個能輸出圓的面積的Java應用程序。 public class ComputerCircleArea
在java中public void與public static void區別
sta erro ati 對象 方法 這樣的 調用 必須 靜態方法 static 方法可以被main方法直接調用,而非static方法不可以。因為static方法是屬於類的,是類方法。可以通過類名.方法名直接調用。而非static方法必須等對象被new出來以後才能使用,因而
Java中重載與重寫的區別
ref 類對象 就是 不同 3.4 做出 同方 相同 默認 簡單的個人記憶,重寫是子類中的方法與父類的方法參數、返回值一模一樣,重載是對於同一個類中的方法,方法名相同,參數類型、個數不同。當父類的引用指向子類對象的時候,子類中如果有對於父類方法的重寫,則調用的是子類重寫過的
Java中自動裝箱與拆箱詳解
sans 做的 sys 實例 代碼 而在 byte 裝箱 bsp 在講裝箱與拆箱之前我們要先了解一下這個問題的來源: Java中的類型分為基本類型(Primitive type)和類類型(Class type)兩種: 基本類型包括byte型、char型、short型
java中的equals與==
bsp 源碼 內部 brush ++ class object類 功能 length equals()與==都是java中用於進行比較的,返回boolean值,不同的是equals()是Object類中定義的一個方法,==是一個比較運算符。下面是equals()在O
(五)聊一聊深Copy與淺Copy
otto list int print 技術分享 作用 code height 工廠 一、關於淺copy與深copy 首先說明一下: 在python中,賦值其實就是對象的引用,變量就是對象的一個標簽,如果把內存對象比喻成一個個房間,那麽變量就是門牌號。 深copy與淺
java中的常量與變量學習記錄
進行 變量類型 過程 java OS 變化 邏輯 存儲 nal 常量的定義:程序運行過程中,其值不會發生變化(更準確的說是不可以發生變化)的量叫做常量。 常量的作用:簡單、直觀的描述一個東西,是變量的基礎,是程序運行的基礎。 常量分為兩大類:一類:原始值(不需要定義即可使用
java中的裝箱與拆箱
net chan import HA com 裝箱 ava art spa java中的裝箱與拆箱 ,參考這三個博客,寫的很好 1 http://www.importnew.com/15712.html 2 https://www.cnblogs.com/dol
JAVA中的BigInteger與BigDecimal類功能強大
取余 並且 log 加減乘除 value java 構造函數 () eof BigInteger類是java為了處理大數字二專門制作的類,可以處理很大的數字(理論上無限大),並且可以實現大數字的類似於int所有數學運算。對算法題來說,再也不怕出現超出int範圍的運算了! 同
淺copy與深copy舉例
deepcopy clas 分享 src -s 技術 技術分享 png TP 例1: 1 #!/usr/bin/env python 2 import copy 3 d1 = {‘x‘:1,‘y‘:2,‘z‘:[3,4.5]} 4 d2 = d1 5 d3
Java中的異常與錯誤處理
ror sys lse AC alt xtend tro ima onu 編譯型異常和運行時異常 編譯時異常是指程序正確 而由外界條件不滿足而產生的異常 java 中要求必須去捕捉住這類異常 不然無法通過編譯 運行時異常是指程序存在著bug
JAVA中接口與抽象類
rac 構造 轉換 希望 就是 pub 成員變量 類型 規則 抽象類總結 抽象類的概念:是使用關鍵字abstract修飾的類就是抽象類; 抽象類的產生:當多個不能相互繼承的類具有相同的功能時,就需要將共同的信息向上抽取,放到公共的父類中;如果公共的父類只能描述所有子類都
深copy與淺copy
lib 意義 blog 數據 hat itl 了解 ble copies copy 和 deep copy 是前兩天讓我特別迷惑的兩個 Python 概念。今天下決心花時間搞懂了兩者的區別,更重要的是通過它們認識了 Python 存儲數據的一些有趣特點。 雖然第一次聽說