最近需要用到比較兩個對象屬性的變化,其中一個是oldObj,另外一個是newObj,oldObj是newObj的前一個狀態,所以需要在newObj的某個狀態時,復制一個一樣的對象,由於JAVA不支持深層拷貝,因此專門寫了一個方法
方法實現很簡單,提供兩種方式:
一種是序列化成數據流,前提是所有對象(對象中包含的對象...)都需要繼承Serializable接口,如果都繼承了那很容易,如果沒有繼承,而且也不打算修改所有類,可以用第二種方式。
第二種是將對象序列化為json,通過json來實現拷貝,這種方式需要用到net.sf.json.JSONObject。
具體代碼如下:
復制代碼 代碼如下:
public class DeepCopy {
/**
* 深層拷貝
*
* @param <T>
* @param obj
* @return
* @throws Exception
*/
public static <T> T copy(T obj) throws Exception {
//是否實現了序列化接口,即使該類實現了,他擁有的對象未必也有...
if(Serializable.class.isAssignableFrom(obj.getClass())){
//如果子類沒有繼承該接口,這一步會報錯
try {
return copyImplSerializable(obj);
} catch (Exception e) {
//這裡不處理,會運行到下面的嘗試json
}
}
//如果序列化失敗,嘗試json序列化方式
if(hasJson()){
try {
return copyByJson(obj);
} catch (Exception e) {
//這裡不處理,下面返回null
}
}
return null;
}
/**
* 深層拷貝 - 需要類繼承序列化接口
* @param <T>
* @param obj
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static <T> T copyImplSerializable(T obj) throws Exception {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
Object o = null;
//如果子類沒有繼承該接口,這一步會報錯
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
bais = new ByteArrayInputStream(baos.toByteArray());
ois = new ObjectInputStream(bais);
o = ois.readObject();
return (T) o;
} catch (Exception e) {
throw new Exception("對象中包含沒有繼承序列化的對象");
} finally{
try {
baos.close();
oos.close();
bais.close();
ois.close();
} catch (Exception e2) {
//這裡報錯不需要處理
}
}
}
/**
* 是否可以使用json
* @return
*/
private static boolean hasJson(){
try {
Class.forName("net.sf.json.JSONObject");
return true;
} catch (Exception e) {
return false;
}
}
/**
* 深層拷貝 - 需要net.sf.json.JSONObject
* @param <T>
* @param obj
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static <T> T copyByJson(T obj) throws Exception {
return (T)JSONObject.toBean(JSONObject.fromObject(obj),obj.getClass());
}
}
只需要調用copy方法就行。