一種c#深拷貝方式完勝java深拷貝(實(shí)現(xiàn)上的對(duì)比分析)
樓主是一名asp.net攻城獅,最近經(jīng)常跑java組客串幫忙開(kāi)發(fā),所以最近對(duì)java的一些基礎(chǔ)知識(shí)特別上心。卻遇到需要將一個(gè)對(duì)象深拷貝出來(lái)做其他事情,而原對(duì)象保持原有狀態(tài)的情況。(實(shí)在是不想自己new一個(gè)出來(lái),然后對(duì)著一堆字段賦值......好吧,再此之前我沒(méi)有關(guān)心是否項(xiàng)目框架有深拷貝的方法),然后就想著用反射實(shí)現(xiàn)吧....接下來(lái)
是我自己的原因,還是真的不存在這樣的純用反射實(shí)現(xiàn)的深拷貝方式....(c#是有純反射實(shí)現(xiàn)的)
但也不能算自己白忙活吧,也找到了其他實(shí)現(xiàn)深拷貝的方式(但是每種方式我都覺(jué)得并不是太合理,也許是因?yàn)閏#的方式帶入了吧,最后貼出c#版本純反射實(shí)現(xiàn)深拷貝的代碼)
方式一:實(shí)現(xiàn)Cloneable接口,重寫(xiě)clone方法
實(shí)體類:一個(gè)輪胎類,一個(gè)車輛類,車輛中包含輪胎
/**輪胎類**/
public class Tire implements Cloneable {
public String color;
public int radius;
public Tire(){}
public Tire(String color, int radius) {
this.color = color;
this.radius = radius;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**車輛類**/
public class Car implements Cloneable{
public String name;
public String color;
public Tire tire;
public Car() {}
public Car(String name, String color, Tire tire) {
this.name = name;
this.color = color;
this.tire = tire;
}
public void whistle(){
System.out.println("汽車"+this.name+" 鳴笛...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
@Test
public void test() throws CloneNotSupportedException {
Tire tire = new Tire("black",100);
Car car = new Car("奔馳","white",tire);
Car car_copy = (Car)car.clone();
System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode());
System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode());
car_copy.color = "blue";
System.out.println("car_copy:"+car_copy.color+" car:"+car.color);
}
輸出結(jié)果:
car:1223737555 car.tire:906199566 car_copy:542081238 car_copy.tire:906199566 car_copy:blue car:white
從結(jié)果可以的之,car與car_copy的內(nèi)存地址并不一致,但car.tire與car_copy.tire的內(nèi)存地址卻是一致的,說(shuō)明“奔馳”車確實(shí)又造出了一輛,但卻公用同一幅輪胎(這種情形....哈哈哈),好吧,也就是只復(fù)制了tire的引用,這可以說(shuō)是深拷貝的不徹底 (hashCode()的值可以當(dāng)作是內(nèi)存地址來(lái)理解),那么要怎樣才能徹底,真正的深拷貝?
修改Car類中的clone方法:
@Override
protected Object clone() throws CloneNotSupportedException {
Car car = (Car)super.clone();
car.tire = (Tire)car.tire.clone();
return car;
}
輸出結(jié)果:
car:1223737555 car.tire:906199566 car_copy:542081238 car_copy.tire:1133736492 car_copy:blue car:white
這樣最終實(shí)現(xiàn)了,但這種方式用到項(xiàng)目中并不是很合適吧,每個(gè)需要深拷貝的類,都要實(shí)現(xiàn)Cloneable接口,并覆蓋其clone方法,遇到引用其他類時(shí)候更是需要修改clone方法,要是引用其他類,其他類再引用其他類呢?這不好吧......
方式二:通過(guò)序列化與反序列化實(shí)現(xiàn)(實(shí)現(xiàn)Serializable接口)
實(shí)體類:與第一種方式類似,換成實(shí)現(xiàn)Serializable接口,去掉clone方法
/**輪胎類**/
@SuppressWarnings("serial")
public class Tire implements java.io.Serializable {
public String color;
public int radius;
public Tire(){}
public Tire(String color, int radius) {
this.color = color;
this.radius = radius;
}
}
/**車輛類**/
@SuppressWarnings("serial")
public class Car implements java.io.Serializable{
public String name;
public String color;
public Tire tire;
public Car() {}
public Car(String name, String color, Tire tire) {
this.name = name;
this.color = color;
this.tire = tire;
}
public void whistle(){
System.out.println("汽車"+this.name+" 鳴笛...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
}
深拷貝方法:
@SuppressWarnings("unchecked")
public static Object deepClone(Object obj)
{
Object copyObj = null;
ObjectOutputStream out = null;
ObjectInputStream in = null;
try {
// 序列化
ByteArrayOutputStream bufferOut = new ByteArrayOutputStream();
out = new ObjectOutputStream(bufferOut);
out.writeObject(obj);
// 反序列化
ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray());
in = new ObjectInputStream(bufferIn);
copyObj = in.readObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try{
if(in != null){
in.close();
}
if(out!=null){
out.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}
}
return copyObj;
}
單元測(cè)試:
@Test
public void test() throws CloneNotSupportedException {
Tire tire = new Tire("black",100);
Car car = new Car("奔馳","white",tire);
Car car_copy = (Car)deepClone(car);
System.out.println("car:"+car.hashCode()+" car.tire:"+car.tire.hashCode());
System.out.println("car_copy:"+car_copy.hashCode()+" car_copy.tire:"+car_copy.tire.hashCode());
car_copy.color = "blue";
System.out.println("car_copy:"+car_copy.color+" car:"+car.color);
}
輸出結(jié)果:
car:2019524978 car.tire:855703640 car_copy:1407965019 car_copy.tire:545768040 car_copy:blue car:white
從結(jié)果集中可以看出是深拷貝是正確的,但是每個(gè)類還是需要實(shí)現(xiàn)Serializable,好像也不合適吧......
優(yōu)化一下深拷貝方法:將其換成泛型,這樣拷貝出來(lái)就不需要強(qiáng)轉(zhuǎn)了(好吧,其實(shí)也沒(méi)比上面的方法好到哪去...)
@SuppressWarnings("unchecked")
public static <T> T deepClone(T obj)
{
T copyObj = null;
ObjectOutputStream out = null;
ObjectInputStream in = null;
try {
// 序列化
ByteArrayOutputStream bufferOut = new ByteArrayOutputStream();
out = new ObjectOutputStream(bufferOut);
out.writeObject(obj);
// 反序列化
ByteArrayInputStream bufferIn = new ByteArrayInputStream(bufferOut.toByteArray());
in = new ObjectInputStream(bufferIn);
copyObj = (T)in.readObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try{
if(in != null){
in.close();
}
if(out!=null){
out.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}
}
return copyObj;
}
通過(guò)序列化與反序列化深拷貝還有更簡(jiǎn)單的實(shí)現(xiàn)方式,就是需要導(dǎo)個(gè)包(拷貝的類也必須實(shí)現(xiàn)Serializable接口),當(dāng)然,我已經(jīng)為你們準(zhǔn)備好了 點(diǎn)擊->org.apache.commons.lang
深拷貝方法:就一行代碼...
public Object deepClone(Object obj){
return org.apache.commons.lang.SerializationUtils.clone((Serializable)obj);
}
好了,java的暫時(shí)就到這里了,當(dāng)然對(duì)于這兩種方式并不是很滿意...
-------------------------------------------------
C#深拷貝 反射實(shí)現(xiàn)
下面方法是c#的深拷貝,純反射實(shí)現(xiàn),無(wú)需實(shí)現(xiàn)任何接口,哦對(duì),需要實(shí)體類有個(gè)無(wú)參的構(gòu)造方法,簡(jiǎn)單使用強(qiáng)大,微軟大法好啊......有需要用到的同學(xué)就拿去用吧,目前經(jīng)過(guò)一個(gè)幾百W的項(xiàng)目框架中考驗(yàn),真的強(qiáng)大實(shí)用
/// <summary>
/// 對(duì)象拷貝
/// </summary>
/// <param name="obj">被復(fù)制對(duì)象</param>
/// <returns>新對(duì)象</returns>
private object CopyOjbect(object obj) {
if (obj == null) {
return null;
}
Object targetDeepCopyObj;
Type targetType = obj.GetType();
//值類型
if (targetType.IsValueType == true) {
targetDeepCopyObj = obj;
}
//引用類型
else {
targetDeepCopyObj = System.Activator.CreateInstance(targetType); //創(chuàng)建引用對(duì)象
System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers();
foreach (System.Reflection.MemberInfo member in memberCollection) {
//拷貝字段
if (member.MemberType == System.Reflection.MemberTypes.Field)
{
System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member;
Object fieldValue = field.GetValue(obj);
if (fieldValue is ICloneable)
{
field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());
}
else
{
field.SetValue(targetDeepCopyObj, CopyOjbect(fieldValue));
}
}//拷貝屬性
else if (member.MemberType == System.Reflection.MemberTypes.Property) {
System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member;
MethodInfo info = myProperty.GetSetMethod(false);
if (info != null) {
try {
object propertyValue = myProperty.GetValue(obj, null);
if (propertyValue is ICloneable) {
myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);
}
else {
myProperty.SetValue(targetDeepCopyObj, CopyOjbect(propertyValue), null);
}
}
catch (System.Exception ex) {
}
}
}
}
}
return targetDeepCopyObj;
}
以上這篇一種c#深拷貝方式完勝java深拷貝(實(shí)現(xiàn)上的對(duì)比分析)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持我們。
單元測(cè)試:
欄 目:C#教程
下一篇:C#簡(jiǎn)單實(shí)現(xiàn)顯示中文格式星期幾的方法
本文標(biāo)題:一種c#深拷貝方式完勝java深拷貝(實(shí)現(xiàn)上的對(duì)比分析)
本文地址:http://m.jygsgssxh.com/a1/C_jiaocheng/6364.html
您可能感興趣的文章
- 01-10深入淺出23種設(shè)計(jì)模式
- 01-10C#類的多態(tài)性詳解
- 01-10C#中深度復(fù)制和淺度復(fù)制詳解
- 01-10輕松學(xué)習(xí)C#的基礎(chǔ)入門
- 01-10輕松學(xué)習(xí)C#的哈希表
- 01-10輕松學(xué)習(xí)C#的抽象類
- 01-10深入解析C#編程中struct所定義的結(jié)構(gòu)
- 01-10深入解析C#中的交錯(cuò)數(shù)組與隱式類型的數(shù)組
- 01-10深入解析C#中的abstract抽象類
- 01-10深入講解C#編程中嵌套類型和匿名類型的定義與使用


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫(xiě)Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery


