gpt4 book ai didi

一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

楼主是一名asp.net攻城狮,最近经常跑java组客串帮忙开发,所以最近对java的一些基础知识特别上心。却遇到需要将一个对象深拷贝出来做其他事情,而原对象保持原有状态的情况。(实在是不想自己new一个出来,然后对着一堆字段赋值......好吧,再此之前我没有关心是否项目框架有深拷贝的方法),然后就想着用反射实现吧....接下来 。

一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)

是我自己的原因,还是真的不存在这样的纯用反射实现的深拷贝方式....(c#是有纯反射实现的) 。

但也不能算自己白忙活吧,也找到了其他实现深拷贝的方式(但是每种方式我都觉得并不是太合理,也许是因为c#的方式带入了吧,最后贴出c#版本纯反射实现深拷贝的代码) 。

方式一:实现Cloneable接口,重写clone方法 。

实体类:一个轮胎类,一个车辆类,车辆中包含轮胎 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**轮胎类**/
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();
   }
}

  。

  。

?
1
2
3
4
5
6
7
8
9
10
@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);
   }

输出结果:

?
1
2
3
car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:906199566
car_copy:blue car:white

从结果可以的之,car与car_copy的内存地址并不一致,但car.tire与car_copy.tire的内存地址却是一致的,说明“奔驰”车确实又造出了一辆,但却公用同一幅轮胎(这种情形....哈哈哈),好吧,也就是只复制了tire的引用,这可以说是深拷贝的不彻底 (hashCode()的值可以当作是内存地址来理解),那么要怎样才能彻底,真正的深拷贝?

修改Car类中的clone方法:

?
1
2
3
4
5
6
@Override
   protected Object clone() throws CloneNotSupportedException {
     Car car = (Car)super.clone();
     car.tire = (Tire)car.tire.clone();
     return car;
   }

输出结果:

?
1
2
3
car:1223737555 car.tire:906199566
car_copy:542081238 car_copy.tire:1133736492
car_copy:blue car:white

这样最终实现了,但这种方式用到项目中并不是很合适吧,每个需要深拷贝的类,都要实现Cloneable接口,并覆盖其clone方法,遇到引用其他类时候更是需要修改clone方法,要是引用其他类,其他类再引用其他类呢?这不好吧...... 。

方式二:通过序列化与反序列化实现(实现Serializable接口) 。

实体类:与第一种方式类似,换成实现Serializable接口,去掉clone方法 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**轮胎类**/
@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;
   }
}

深拷贝方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@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;
   }

单元测试:

?
1
2
3
4
5
6
7
8
9
10
@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);
   }

输出结果:

?
1
2
3
car:2019524978 car.tire:855703640
car_copy:1407965019 car_copy.tire:545768040
car_copy:blue car:white

从结果集中可以看出是深拷贝是正确的,但是每个类还是需要实现Serializable,好像也不合适吧...... 。

优化一下深拷贝方法:将其换成泛型,这样拷贝出来就不需要强转了(好吧,其实也没比上面的方法好到哪去...) 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@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;
   }

通过序列化与反序列化深拷贝还有更简单的实现方式,就是需要导个包(拷贝的类也必须实现Serializable接口),当然,我已经为你们准备好了 点击->org.apache.commons.lang 。

深拷贝方法:就一行代码... 。

?
1
2
3
public Object deepClone(Object obj){
      return org.apache.commons.lang.SerializationUtils.clone((Serializable)obj);
    }

好了,java的暂时就到这里了,当然对于这两种方式并不是很满意... 。

------------------------------------------------- 。

C#深拷贝 反射实现 。

下面方法是c#的深拷贝,纯反射实现,无需实现任何接口,哦对,需要实体类有个无参的构造方法,简单使用强大,微软大法好啊......有需要用到的同学就拿去用吧,目前经过一个几百W的项目框架中考验,真的强大实用 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/// <summary>
     /// 对象拷贝
     /// </summary>
     /// <param name="obj">被复制对象</param>
     /// <returns>新对象</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);  //创建引用对象 
         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深拷贝(实现上的对比分析)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我.

最后此篇关于一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)的文章就讲到这里了,如果你想了解更多关于一种c#深拷贝方式完胜java深拷贝(实现上的对比分析)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com