码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA 对象拷贝

时间:2014-08-27 01:35:46      阅读:437      评论:0      收藏:0      [点我收藏+]

标签:blog   http   os   java   使用   io   ar   数据   art   

JAVA 对象拷贝

为什么需要有对象拷贝?

对象拷贝相对的自然是引用拷贝。java初学者经常会问,我这个方法要改变一个对象的属性,可以把参数传进去了,为什么没有改变了?

——基本数据类型传值,而对象传引用或引用的拷贝。

而有时候我们要获取到一个当前状态的对象复制品,他们是两个独立对象。不再是引用或者引用拷贝(实质都是指向对象本身)。就是说a是b的拷贝,b发生变化的时候,不要影响a。


对象拷贝有浅拷贝和深度拷贝两种。

1)浅拷贝

浅拷贝是指对象中基本数据类型得到拷贝,而引用数据类型并未拷贝。
提到拷贝自然和clone联系起来了,所有具有clone功能的类都有一个特性,那就是它直接或间接地实现了Cloneable接口。
否则,我们在尝试调用clone()方法时,将会触发CloneNotSupportedException异常。
eg:

 1 bubuko.com,布布扣 public   class  DOG  implements  Cloneable
 2 bubuko.com,布布扣 {
 3 bubuko.com,布布扣     public  DOG(String name,  int  age)
 4 bubuko.com,布布扣      {
 5 bubuko.com,布布扣         this .name  =  name;
 6 bubuko.com,布布扣         this .age  =  age;
 7 bubuko.com,布布扣    } 
 8 bubuko.com,布布扣 
 9 bubuko.com,布布扣     public  String getName()
10 bubuko.com,布布扣      {
11 bubuko.com,布布扣         return   this .name;
12 bubuko.com,布布扣    } 
13 bubuko.com,布布扣 
14 bubuko.com,布布扣     public   int  getAge()
15 bubuko.com,布布扣      {
16 bubuko.com,布布扣         return   this .age;
17 bubuko.com,布布扣    } 
18 bubuko.com,布布扣 
19 bubuko.com,布布扣     public  Object clone()
20 bubuko.com,布布扣      {
21 bubuko.com,布布扣         try 
22 bubuko.com,布布扣          {
23 bubuko.com,布布扣             return   super .clone();
24 bubuko.com,布布扣 
25 bubuko.com,布布扣        }   catch  (CloneNotSupportedException e)
26 bubuko.com,布布扣          {
27 bubuko.com,布布扣             return   null ;
28 bubuko.com,布布扣        } 
29 bubuko.com,布布扣    } 
30 bubuko.com,布布扣 
31 bubuko.com,布布扣     public  String name;
32 bubuko.com,布布扣 
33 bubuko.com,布布扣     private   int  age;
34 bubuko.com,布布扣 
35 bubuko.com,布布扣     // test 
36 bubuko.com,布布扣      public   static   void  main(String[] args)
37 bubuko.com,布布扣      {
38 bubuko.com,布布扣        DOG dog1  =   new  DOG( " xiaogou " ,  2 );
39 bubuko.com,布布扣        DOG dog2  =  (DOG) dog1.clone();
40 bubuko.com,布布扣        dog1.name  =   " dagou " ;
41 bubuko.com,布布扣        System.out.println(dog2.getName());
42 bubuko.com,布布扣        System.out.println(dog2.getAge());
43 bubuko.com,布布扣        System.out.println(dog1.getName());
44 bubuko.com,布布扣        System.out.println(dog1.getAge());
45 bubuko.com,布布扣 
46 bubuko.com,布布扣    } 
47 bubuko.com,布布扣 
48 bubuko.com,布布扣
49 bubuko.com,布布扣



运行结果:

xiaogou
2
dagou
2

2)深度拷贝

相对浅拷贝。实现对象中基本数据类型和引用数据类型的拷贝。

请先看下面代码:

 

 1 bubuko.com,布布扣 class  AAA
 2 bubuko.com,布布扣 {
 3 bubuko.com,布布扣     public  AAA(String name)
 4 bubuko.com,布布扣      {
 5 bubuko.com,布布扣         this .name  =  name;
 6 bubuko.com,布布扣    } 
 7 bubuko.com,布布扣 
 8 bubuko.com,布布扣     public  String name;
 9 bubuko.com,布布扣
10 bubuko.com,布布扣 
11 bubuko.com,布布扣 class  DOG  implements  Cloneable
12 bubuko.com,布布扣 {
13 bubuko.com,布布扣     public  DOG(String name,  int  age, AAA birthday)
14 bubuko.com,布布扣      {
15 bubuko.com,布布扣         this .name  =  name;
16 bubuko.com,布布扣         this .age  =  age;
17 bubuko.com,布布扣         this .birthday  =  birthday;
18 bubuko.com,布布扣    } 
19 bubuko.com,布布扣 
20 bubuko.com,布布扣     public  String getName()
21 bubuko.com,布布扣      {
22 bubuko.com,布布扣         return  name;
23 bubuko.com,布布扣    } 
24 bubuko.com,布布扣 
25 bubuko.com,布布扣     public   int  getAge()
26 bubuko.com,布布扣      {
27 bubuko.com,布布扣         return  age;
28 bubuko.com,布布扣    } 
29 bubuko.com,布布扣 
30 bubuko.com,布布扣     public  AAA getBirthday()
31 bubuko.com,布布扣      {
32 bubuko.com,布布扣         return  birthday;
33 bubuko.com,布布扣    } 
34 bubuko.com,布布扣 
35 bubuko.com,布布扣     public  String getBirth(AAA a)
36 bubuko.com,布布扣      {
37 bubuko.com,布布扣         return  a.name;
38 bubuko.com,布布扣    } 
39 bubuko.com,布布扣 
40 bubuko.com,布布扣     public  String name;
41 bubuko.com,布布扣 
42 bubuko.com,布布扣     private   int  age;
43 bubuko.com,布布扣 
44 bubuko.com,布布扣     public  AAA birthday;
45 bubuko.com,布布扣 
46 bubuko.com,布布扣     public  Object clone()
47 bubuko.com,布布扣      {
48 bubuko.com,布布扣         try 
49 bubuko.com,布布扣          {
50 bubuko.com,布布扣             super .clone();
51 bubuko.com,布布扣             return   super .clone();
52 bubuko.com,布布扣        }   catch  (Exception e)
53 bubuko.com,布布扣          {
54 bubuko.com,布布扣             return   null ;
55 bubuko.com,布布扣        } 
56 bubuko.com,布布扣    } 
57 bubuko.com,布布扣
58 bubuko.com,布布扣 
59 bubuko.com,布布扣 public   class  TestClone
60 bubuko.com,布布扣 {
61 bubuko.com,布布扣     public   static   void  main(String[] args)
62 bubuko.com,布布扣      {
63 bubuko.com,布布扣        AAA Day  =   new  AAA( " test " );
64 bubuko.com,布布扣        DOG dog1  =   new  DOG( " xiaogou " ,  2 , Day);
65 bubuko.com,布布扣        DOG dog2  =  (DOG) dog1.clone();
66 bubuko.com,布布扣         //   dog2.birthday = (AAA) dog1.birthday.clone();  
67 bubuko.com,布布扣         dog1.birthday.name  =   " 333 " ;
68 bubuko.com,布布扣        System.out.println(dog1.getBirth(dog1.birthday));
69 bubuko.com,布布扣        System.out.println(dog2.getBirth(dog2.birthday));
70 bubuko.com,布布扣    } 
71 bubuko.com,布布扣
72 bubuko.com,布布扣


运行结果是:
333
333
而真正要实现拷贝还的加点代码,如下请对比上面和下面代码的异同之处:

 1 bubuko.com,布布扣 class  AAA  implements  Cloneable
 2 bubuko.com,布布扣 {
 3 bubuko.com,布布扣     public  AAA(String name)
 4 bubuko.com,布布扣      {
 5 bubuko.com,布布扣         this .name  =  name;
 6 bubuko.com,布布扣    } 
 7 bubuko.com,布布扣 
 8 bubuko.com,布布扣     public  Object clone()
 9 bubuko.com,布布扣      {
10 bubuko.com,布布扣         try 
11 bubuko.com,布布扣          {
12 bubuko.com,布布扣             super .clone();
13 bubuko.com,布布扣             return   super .clone();
14 bubuko.com,布布扣        }   catch  (Exception e)
15 bubuko.com,布布扣          {
16 bubuko.com,布布扣             return   null ;
17 bubuko.com,布布扣        } 
18 bubuko.com,布布扣    } 
19 bubuko.com,布布扣 
20 bubuko.com,布布扣     public  String name;
21 bubuko.com,布布扣
22 bubuko.com,布布扣 
23 bubuko.com,布布扣 class  DOG  implements  Cloneable
24 bubuko.com,布布扣 {
25 bubuko.com,布布扣     public  DOG(String name,  int  age, AAA birthday)
26 bubuko.com,布布扣      {
27 bubuko.com,布布扣         this .name  =  name;
28 bubuko.com,布布扣         this .age  =  age;
29 bubuko.com,布布扣         this .birthday  =  birthday;
30 bubuko.com,布布扣    } 
31 bubuko.com,布布扣 
32 bubuko.com,布布扣     public  String getName()
33 bubuko.com,布布扣      {
34 bubuko.com,布布扣         return  name;
35 bubuko.com,布布扣    } 
36 bubuko.com,布布扣 
37 bubuko.com,布布扣     public   int  getAge()
38 bubuko.com,布布扣      {
39 bubuko.com,布布扣         return  age;
40 bubuko.com,布布扣    } 
41 bubuko.com,布布扣 
42 bubuko.com,布布扣     public  AAA getBirthday()
43 bubuko.com,布布扣      {
44 bubuko.com,布布扣         return  birthday;
45 bubuko.com,布布扣    } 
46 bubuko.com,布布扣 
47 bubuko.com,布布扣     public  String getBirth(AAA a)
48 bubuko.com,布布扣      {
49 bubuko.com,布布扣         return  a.name;
50 bubuko.com,布布扣    } 
51 bubuko.com,布布扣 
52 bubuko.com,布布扣     public  String name;
53 bubuko.com,布布扣 
54 bubuko.com,布布扣     private   int  age;
55 bubuko.com,布布扣 
56 bubuko.com,布布扣     public  AAA birthday;
57 bubuko.com,布布扣 
58 bubuko.com,布布扣     public  Object clone()
59 bubuko.com,布布扣      {
60 bubuko.com,布布扣         try 
61 bubuko.com,布布扣          {
62 bubuko.com,布布扣             super .clone();
63 bubuko.com,布布扣             return   super .clone();
64 bubuko.com,布布扣        }   catch  (Exception e)
65 bubuko.com,布布扣          {
66 bubuko.com,布布扣             return   null ;
67 bubuko.com,布布扣        } 
68 bubuko.com,布布扣    } 
69 bubuko.com,布布扣
70 bubuko.com,布布扣 
71 bubuko.com,布布扣 public   class  TestClone
72 bubuko.com,布布扣 {
73 bubuko.com,布布扣     public   static   void  main(String[] args)
74 bubuko.com,布布扣      {
75 bubuko.com,布布扣        AAA Day  =   new  AAA( " test " );
76 bubuko.com,布布扣        DOG dog1  =   new  DOG( " xiaogou " ,  2 , Day);
77 bubuko.com,布布扣        DOG dog2  =  (DOG) dog1.clone();
78 bubuko.com,布布扣        dog2.birthday  =  (AAA) dog1.birthday.clone(); // 特别注意这里 
79 bubuko.com,布布扣         dog1.birthday.name  =   " 333 " ;
80 bubuko.com,布布扣        System.out.println(dog1.getBirth(dog1.birthday));
81 bubuko.com,布布扣        System.out.println(dog2.getBirth(dog2.birthday));
82 bubuko.com,布布扣    } 
83 bubuko.com,布布扣
84 bubuko.com,布布扣


运行结果:
333
test
这样基本就达到了我们当初的母的。


但是明显的这种方法还是有许多不足,人们总是希望一个clone就是对象直接克隆。而上面还要对对象中的对象递归使用clone。下面提供一种更高级点的做法:

 

 1 bubuko.com,布布扣 import  java.io. * ;
 2 bubuko.com,布布扣 
 3 bubuko.com,布布扣 class  AAA  implements  Serializable
 4 bubuko.com,布布扣 {
 5 bubuko.com,布布扣     public  AAA(String name)
 6 bubuko.com,布布扣      {
 7 bubuko.com,布布扣         this .name  =  name;
 8 bubuko.com,布布扣    } 
 9 bubuko.com,布布扣 
10 bubuko.com,布布扣     public  String name;
11 bubuko.com,布布扣
12 bubuko.com,布布扣 
13 bubuko.com,布布扣 class  DOG  extends  SerialCloneable
14 bubuko.com,布布扣 {
15 bubuko.com,布布扣     public  DOG(String name,  int  age, AAA birthday)
16 bubuko.com,布布扣      {
17 bubuko.com,布布扣         this .name  =  name;
18 bubuko.com,布布扣         this .age  =  age;
19 bubuko.com,布布扣         this .birthday  =  birthday;
20 bubuko.com,布布扣    } 
21 bubuko.com,布布扣 
22 bubuko.com,布布扣     public  String getName()
23 bubuko.com,布布扣      {
24 bubuko.com,布布扣         return  name;
25 bubuko.com,布布扣    } 
26 bubuko.com,布布扣 
27 bubuko.com,布布扣     public   int  getAge()
28 bubuko.com,布布扣      {
29 bubuko.com,布布扣         return  age;
30 bubuko.com,布布扣    } 
31 bubuko.com,布布扣 
32 bubuko.com,布布扣     public  AAA getBirthday()
33 bubuko.com,布布扣      {
34 bubuko.com,布布扣         return  birthday;
35 bubuko.com,布布扣    } 
36 bubuko.com,布布扣 
37 bubuko.com,布布扣     public  String getBirth(AAA a)
38 bubuko.com,布布扣      {
39 bubuko.com,布布扣         return  a.name;
40 bubuko.com,布布扣    } 
41 bubuko.com,布布扣 
42 bubuko.com,布布扣     public  String name;
43 bubuko.com,布布扣 
44 bubuko.com,布布扣     private   int  age;
45 bubuko.com,布布扣 
46 bubuko.com,布布扣     public  AAA birthday;
47 bubuko.com,布布扣 
48 bubuko.com,布布扣     public  Object clone()
49 bubuko.com,布布扣      {
50 bubuko.com,布布扣         try 
51 bubuko.com,布布扣          {
52 bubuko.com,布布扣             super .clone();
53 bubuko.com,布布扣             return   super .clone();
54 bubuko.com,布布扣        }   catch  (Exception e)
55 bubuko.com,布布扣          {
56 bubuko.com,布布扣             return   null ;
57 bubuko.com,布布扣        } 
58 bubuko.com,布布扣    } 
59 bubuko.com,布布扣
60 bubuko.com,布布扣 
61 bubuko.com,布布扣 public   class  TestClone
62 bubuko.com,布布扣 {
63 bubuko.com,布布扣     public   static   void  main(String[] args)
64 bubuko.com,布布扣      {
65 bubuko.com,布布扣        AAA Day  =   new  AAA( " test " );
66 bubuko.com,布布扣        DOG dog1  =   new  DOG( " xiaogou " ,  2 , Day);
67 bubuko.com,布布扣        DOG dog2  =  (DOG) dog1.clone();
68 bubuko.com,布布扣         // dog2.birthday = (AAA) dog1.birthday.clone(); 
69 bubuko.com,布布扣         dog1.birthday.name  =   " 333 " ;
70 bubuko.com,布布扣        System.out.println(dog1.getBirth(dog1.birthday));
71 bubuko.com,布布扣        System.out.println(dog2.getBirth(dog2.birthday));
72 bubuko.com,布布扣    } 
73 bubuko.com,布布扣
74 bubuko.com,布布扣 
75 bubuko.com,布布扣 class  SerialCloneable  implements  Cloneable, Serializable
76 bubuko.com,布布扣 {
77 bubuko.com,布布扣     public  Object clone()
78 bubuko.com,布布扣      {
79 bubuko.com,布布扣         try 
80 bubuko.com,布布扣          {
81 bubuko.com,布布扣            ByteArrayOutputStream bout  =   new  ByteArrayOutputStream();
82 bubuko.com,布布扣            ObjectOutputStream out  =   new  ObjectOutputStream(bout);
83 bubuko.com,布布扣            out.writeObject( this );
84 bubuko.com,布布扣            out.close();
85 bubuko.com,布布扣            ByteArrayInputStream bin  =   new  ByteArrayInputStream(bout
86 bubuko.com,布布扣                    .toByteArray());
87 bubuko.com,布布扣            ObjectInputStream in  =   new  ObjectInputStream(bin);
88 bubuko.com,布布扣            Object ret  =  in.readObject();
89 bubuko.com,布布扣            in.close();
90 bubuko.com,布布扣             return  ret;
91 bubuko.com,布布扣        }   catch  (Exception e)
92 bubuko.com,布布扣          {
93 bubuko.com,布布扣             return   null ;
94 bubuko.com,布布扣        } 
95 bubuko.com,布布扣    } 
96 bubuko.com,布布扣
97 bubuko.com,布布扣


输出:
333
test

上面的代码用序列化与反序列化实现了对象拷贝。比较通用。但是得注意的是其中的类得implements Serializable。

 

3)后记

我们如果利用强大的反射机制+序列化与反序列化,能做出更加灵活的对象拷贝。有兴趣的朋友可以自行去研究。
我在javaeye上看到一篇短文:http://www.javaeye.com/post/367014 主要讲的就是反射在对象拷贝中的应用。

 

JAVA 对象拷贝

标签:blog   http   os   java   使用   io   ar   数据   art   

原文地址:http://www.cnblogs.com/wy-NB/p/3938516.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!