对象的拷贝

对象的拷贝又被成为对象的克隆。对象的拷贝分为两种:浅拷贝和深拷贝。

浅拷贝

浅复制(浅克隆)被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用仍然只指向原来的对象,换言之,浅复制仅仅复制锁考虑的对象,而不复制它所引用的对象。

对象的浅拷贝是通过调用clone方法来实现的。

浅拷贝需要注意的细节:

1. 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
2. Cloneable接口只不过是一个标识接口而已,没有任何方法。
3. 对象的浅克隆也不会调用到构造方法的。

代码示例:

 1 //实体类代码
 2 class Address{
 3
 4     String city;
 5
 6     public Address(String city){
 7         this.city = city;
 8     }
 9
10 }
11
12 public class Person implements Cloneable{
13     int id;
14
15     String name;
16
17     Address address;
18
19     public Person(int id, String name) {
20         this.id = id;
21         this.name = name;
22     }
23     public Person(int id, String name, Address address) {
24         this.id = id;
25         this.name = name;
26         this.address = address;
27         System.out.println("=======构造方法调用了===");
28     }
29     @Override
30     public String toString() {
31         return "编号:"+ this.id+" 姓名:"+ this.name+" 地址:"+ address.city;
32     }
33     @Override
34     public Object clone() throws CloneNotSupportedException {
35         return super.clone();
36     }
37 }
38 //测试类代码
39 public class DemoCopy {
40     public static void main(String[] args) throws CloneNotSupportedException {
41         Person p1 = new Person(110, "Nick",new Address("济南"));
42         Person p2 = (Person)p1.clone();
43         p2.address.city = "北京";
44         System.out.println("p1的内容:"+p1);
45         System.out.println("p2的内容:"+p2);
46     }
47 }

深拷贝

深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,那些引用其他对象的变量将指向被复制过的新对象,而不再试原有的那些被引用的对象,换言之,深复制把要复制的对象所引用的对象都复制了一遍。

把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。

在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。

对象的深拷贝是通过对象输入(ObjectInputStream)输出(ObjectOutputStream)流来实现的。

示例代码如下:

 1 //实体类代码
 2 class Address implements Serializable{
 3
 4     String city;
 5
 6     public Address(String city){
 7         this.city = city;
 8     }
 9
10 }
11
12 public class Person implements Serializable{
13     int id;
14
15     String name;
16
17     Address address;
18
19     public Person(int id, String name) {
20         this.id = id;
21         this.name = name;
22     }
23     public Person(int id, String name, Address address) {
24         this.id = id;
25         this.name = name;
26         this.address = address;
27         System.out.println("=======构造方法调用了===");
28     }
29     @Override
30     public String toString() {
31         return "编号:"+ this.id+" 姓名:"+ this.name+" 地址:"+ address.city;
32     }
33
34 }
35 //测试代码
36 public class Demo2 {
37
38     public static void main(String[] args) throws IOException, ClassNotFoundException {
39         Address address = new Address("广州");
40         Person p1 = new Person(110,"狗娃",address);
41         writeObj(p1);
42         Person p2  =readObj();
43
44         p2.address.city = "长沙";
45         System.out.println("p1:"+ p1);
46         System.out.println("p2:"+ p2);
47
48
49     }
50
51
52     //再从文件中读取对象的信息
53     public static Person readObj() throws ClassNotFoundException, IOException{
54         FileInputStream fileInputStream = new FileInputStream("F:\\obj.txt");
55         //创建对象的输入流对象
56         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
57         return (Person) objectInputStream.readObject();
58     }
59
60
61     //先要把对象写到文件上。
62     public static void writeObj(Person p) throws IOException{
63         //建立一个文件 的输出流对象
64         FileOutputStream fileOutputStream  = new FileOutputStream("F:\\obj.txt");
65         //建立对象的输出流
66         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
67         //把对象写出
68         objectOutputStream.writeObject(p);
69         //关闭资源
70         objectOutputStream.close();
71
72     }
73 }

时间: 2024-10-16 03:51:57

对象的拷贝的相关文章

使用序列化实现对象的拷贝

java提高篇(五)-----使用序列化实现对象的拷贝 分类:            [JAVA开发]-----Java提高篇2013-10-22 19:153668人阅读评论(5)收藏举报 javajava提高篇 摘自:http://blog.csdn.net/chenssy/article/details/12952063 目录(?)[+] 一浅拷贝问题 二利用序列化实现对象的拷贝       我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是

访问修饰限定符的简单总结、final/abstruct/interface对类的限制、自动加载机制、序列化与反序列化【数据持久化和对象的序列化问题】、对象的拷贝(按引用是因为对象标识)和克隆(__clone方法中的this指向)

1.针对访问修饰限定符的理解只需要两点:(1)针对的是类的概念和访问代码的位置来确定是否能够访问(2)对访问修饰限定符的使用时只需要对该成员的使用场景注意即可[也就是内部,继承类,外部进行访问的权限] 不需要对内部进行太多理解[需要对php底层理解时进行理解] [重点][用途]通过访问修饰限定符将内部成员的权限合理的限制,然后再使用公共接口来调用这个基本服务,保证外部不能访问其内部的构件[这样既能够通过类内的设置,将内部的功能实现更好的限制,只有最外层的接口可以正常被访问到,而不了解内部的业务]

使用序列化实现对象的拷贝(转)

   我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常明显.然而我们知道拷贝分为深拷贝和浅拷贝之分,但是浅拷贝存在对象属性拷贝不彻底问题.关于深拷贝.浅拷贝的请参考这里:渐析java的浅拷贝和深拷贝        一.浅拷贝问题       我们先看如下代码: [java] view plaincopyprint? public class Pe

javaScript| 对象的拷贝

上一遍是我们基本素组的拷贝,当然少不了我们对象的拷贝,当然也有我们的浅拷贝和我们的深拷贝滴啦: 然后,深拷贝,从某个角度来说就是我们对象的继承: 对象拷贝分为浅拷贝(shallow)和深拷贝(deep)两种.浅拷贝只复制一层对象的属性,并不会进行递归复制,而javascript存储对象都是存地址的,所以浅拷贝会导致对象中的子对象指向同一块内存地址:而深拷贝则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上 先补充一点基础知识,然

OC学习篇之---对象的拷贝

在前一篇文章中我们说到了如何解决对象的循环引用问题:http://blog.csdn.net/jiangwei0910410003/article/details/41926369,这一篇文章我们就来介绍一下OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC更偏向于Java这种方式,OC中如果一个对象需要被拷贝,他需要实现协议: <NSCopyin

对象属性拷贝工具类的性能比较

一.对象属性拷贝工具类 ”天下武功,唯快不破“.在互联网行业中体现的更加淋淋尽致.我们在业务系统会经常遇到业务对象间属性的拷贝,对如外接口一般都使用特定的DTO对象,而不会使用领域模型,以避免两者的变动互相影响.我们不仅要关注“快”,还要注重CPU的稳定即避免CPU使用的大起大落现象.如何高效完成属性的拷贝并降低对CPU的使用率或避免CPU的抖动. 相关博文已经有很多,为什么还要自己在一篇类似的哪?原因有二:一是加深理解二是比较各自优劣.目前对象间属性的拷贝常用的方法大致如下: 手动拷贝(set

【C++基础 09】避免对象的拷贝

如果我们要使某个类不具备拷贝的功能,可写一个基类(base classes),然后将copy构造函数声明为private且不去实现它. 具体实现如下: class A { public: A(){} private: A(const A&);//copy构造函数为private且不实现它 A& operator=(const A&); }; class B : public A{ public: B(){} ~B(){} }; void main() { A a ; A a1(a)

(转载)OC学习篇之---对象的拷贝

在前一篇文章中我们说到了如何解决对象的循环引用问题,这一篇文章我们就来介绍一下OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC更偏向于Java这种方式,OC中如果一个对象需要被拷贝,他需要实现协议: <NSCopying>.<NSMutableCopying> 从名字上我们可以看到,一个协议是用于不可变对象的,一个协议适用于可变对象

Android SO逆向-对象的拷贝构造函数

0x00 这一节我们主要讨论对象的拷贝构造函数的汇编实现. 0x01 我们直接看C++代码: Test.h: #ifndef _TEST_H_ #define _TEST_H_ #include <android/log.h> #define LOG_TAG "lesson5" #define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) class Test