`

java 序列化 浅克隆 深克隆

阅读更多
序列化
   Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。
    当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
    把Java对象转换为字节序列的过程称为对象的序列化。
    把字节序列恢复为Java对象的过程称为对象的反序列化。
1、序列化的用途
    利用对象的序列化可以保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。
     对象的序列化主要有两种用途:
(a) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
(b) 在网络上传送对象的字节序列。
2、序列化的实现
(1)JDK类库中的序列化API
    java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
     java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
     只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式 。
(2)对象序列化与反序列化的过程
     将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
     对象序列化包括如下步骤:
(a)创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
(b)通过对象输出流的writeObject()方法写对象。
     对象反序列化的步骤如下:
(a)创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
(b)通过对象输入流的readObject()方法读取对象。
     下面让我们来看一个对应的例子,类的内容如下:


Java代码
import java.io.*;  
import java.util.Date;  
public class ObjectSaver {  
          public static void main(String[] args) throws Exception {  
              ObjectOutputStream out = new ObjectOutputStream  
                     (new FileOutputStream("D:""objectFile.obj"));  
              //序列化对象  
              Customer customer = new Customer("阿蜜果", 24);  
              out.writeObject("你好!");  
              out.writeObject(new Date());  
              out.writeObject(customer);  
              out.writeInt(123); //写入基本类型数据  
              out.close();  
              //反序列化对象  
              ObjectInputStream in = new ObjectInputStream  
                     (new FileInputStream("D:""objectFile.obj"));  
              System.out.println("obj1=" + (String) in.readObject());  
              System.out.println("obj2=" + (Date) in.readObject());  
              Customer obj3 = (Customer) in.readObject();  
              System.out.println("obj3=" + obj3);  
              int obj4 = in.readInt();  
              System.out.println("obj4=" + obj4);  
              in.close();  
       }  
}  
class Customer implements Serializable {  
       private String name;  
       private int age;  
       public Customer(String name, int age) {  
              this.name = name;  
              this.age = age;  
       }  
       public String toString() {  
              return "name=" + name + ", age=" + age;  
       }  
}  
import java.io.*;
import java.util.Date;
public class ObjectSaver {
public static void main(String[] args) throws Exception {
ObjectOutputStream out = new ObjectOutputStream
(new FileOutputStream("D:""objectFile.obj"));
//序列化对象
Customer customer = new Customer("阿蜜果", 24);
out.writeObject("你好!");
out.writeObject(new Date());
out.writeObject(customer);
out.writeInt(123); //写入基本类型数据
out.close();
//反序列化对象
ObjectInputStream in = new ObjectInputStream
(new FileInputStream("D:""objectFile.obj"));
System.out.println("obj1=" + (String) in.readObject());
System.out.println("obj2=" + (Date) in.readObject());
Customer obj3 = (Customer) in.readObject();
System.out.println("obj3=" + obj3);
int obj4 = in.readInt();
System.out.println("obj4=" + obj4);
in.close();
}
}
class Customer implements Serializable {
private String name;
private int age;
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "name=" + name + ", age=" + age;
}
}
输出结果如下:

Java代码

obj1=你好!  
obj2=Sat Sep 26 22:02:21 CST 2010  
obj3=name=阿蜜果, age=24  
obj4=123  
obj1=你好!
obj2=Sat Sep 26 22:02:21 CST 2010
obj3=name=阿蜜果, age=24
obj4=123
      因此例比较简单,在此不再详述。
3、serialVersionUID作用:
      序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
       有两种生成方式:
       一个是默认的1L,比如:

Java代码
private static final long serialVersionUID = 1L;  
private static final long serialVersionUID = 1L;
       一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:

Java代码
private static final   long      serialVersionUID = xxxxL; 
private static final   long      serialVersionUID = xxxxL;
二、克隆
      有时想得到对象的一个复制品,该复制品的实体是原对象实体的克隆。复制品实体的变化不会引起原对象实体发生变化,这样的复制品称为原对象实体的克隆对象或简称克隆。
1、浅复制(浅克隆)
      概念:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
      方法:类implements Cloneable,然后重写clone()方法,在clone()方法中调用super.clone()即可,没有其他操作了
2、深复制(深克隆)
      概念:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍
      方法:
(1)类implements Cloneable,然后重写clone()方法,在clone()方法中调用super.clone(),然后还要对引用型变量所指的对象进行克隆。
(2)序列化:将该对象写出到对象输出流,那么用对象输入流读回的对象就是原对象的一个深度克隆
分享到:
评论

相关推荐

    克隆和序列化(Java )

    实现深克隆可能需要自定义的克隆方法,或者使用序列化和反序列化技术。 4. **示例**:`克隆.txt`可能包含以下示例代码: ```java class MyClass implements Cloneable { private Object nestedObj; public ...

    java 深克隆浅克隆

    Java提供了两种主要的克隆方式:深克隆和浅克隆。 1. 浅克隆(Shallow Clone): 浅克隆是通过调用对象的`clone()`方法来实现的,这个方法是Object类提供的。当一个对象被浅克隆时,新创建的对象将拥有原始对象的...

    Java对象的深克隆与浅克隆详解.zip(wcb2003)

    实现深克隆的方法通常需要自定义序列化和反序列化过程,因为Java的标准`clone()`方法不支持深克隆。可以使用`java.io.ObjectOutputStream`和`java.io.ObjectInputStream`来实现: ```java public class MyClass ...

    基于序列化存取实现java对象深度克隆的方法详解

    此外,序列化和反序列化的过程有一定的性能开销,因此,如果只是简单地复制对象而不需要深克隆,考虑使用浅克隆或者拷贝构造函数可能会更有效率。总的来说,基于序列化实现的深克隆是一种强大的工具,尤其适用于处理...

    java的深度克隆的例子

    首先,Java提供了两种基本的克隆方式:浅克隆(shallow clone)和深克隆。浅克隆仅仅复制对象本身,而不复制对象所引用的对象。而深克隆则会递归地复制对象及所有引用的对象,确保新创建的对象和原始对象及其引用的...

    一款轻量级Java对象高效克隆框架,提供高性能的深克隆(非对象->序列化->对象这种低效率克隆)、浅克隆,支持分区克隆

    示例Bean.java 公共类ExampleBean { 私有 int id; 私人用户用户; 私人名单名单; 公共 int getId() { 返回ID; } 公共无效setId(int id){ 这个.id = id; } 公共用户 getUser() { 返回用户; } ...

    java 对象克隆

    对于复杂的对象结构,可以使用序列化和反序列化技术来实现深克隆。首先,将对象序列化为字节数组,然后反序列化为新的对象。这种方法可以确保所有引用类型的对象也被复制。 ```java import java.io.*; public ...

    如何进行Java对象的克隆.pdf

    在 Java 中,实现深克隆可以通过序列化(Serialization)和反序列化(Deserialization)来实现。这是因为序列化可以将对象的所有成员变量转换为字节流,然后可以将字节流反序列化成一个新的对象。 在 Java 中,...

    Java对象(最后面是序列化的知识)1

    Java编程语言中,对象的创建和管理涉及到一系列...总结来说,Java对象的生命周期涉及类加载、初始化,以及对象的创建、克隆、序列化和反序列化等步骤,每一步都可能需要特定的处理和优化,以满足不同的需求和安全考虑。

    JAVA_对象克隆

    4. 克隆可能会带来性能开销,对于大量对象的复制,要考虑其他替代方案,如拷贝构造函数或序列化。 5. 避免使用`clone()`方法来解决所有复制对象的需求,因为其易用性和灵活性有限,尤其是在面对复杂的对象结构时。...

    java深复制浅复制的实现源代码

    为了解决这个问题,可以使用序列化和反序列化的方法实现深复制,或者使用第三方库如Apache Commons Lang的`SerializationUtils.clone()`方法。 另外,提到“实现java类之间的多对多联系”,在Java中,多对多关系...

    深入JAVA对象深度克隆的详解

    在Java中,深度克隆与浅克隆的区别在于处理对象内部引用的复杂性。浅克隆只复制对象本身,而不复制它所引用的对象,而深度克隆则会递归地复制对象及其引用的所有子对象。 当对象包含复杂的数据结构,如集合或嵌套的...

    android 浅复制和深复制-Java Generic Deep Copy 篇

    在Android中,我们常常需要复制Parcelable或Serializable类型的对象,因为它们是Android系统支持的数据传输和序列化方式。对于Parcelable,我们可以使用`Parcel`类的`writeParcelable`和`readParcelable`方法进行...

    解析JAVA深度克隆与浅度克隆的区别详解

    /* 浅克隆 */ newSimpleClone = (SimpleClone)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return newSimpleClone; } ``` 在这个例子中,`SimpleClone`类有一个`Clone...

    java-6个机制.doc

    Java的六个核心机制是编程中不可或缺的部分,它们包括克隆机制、序列化机制、多线程机制、反射机制以及垃圾回收机制和异常处理机制。在这篇文章中,我们将深入探讨前三个机制。 首先,克隆机制允许我们在内存中复制...

    Java面试资料之IO相关

    在 Object 基类中,有一个方法叫 clone,产生一个前期对象的克隆,克隆对象是原对象的拷贝,由于引用类型的存在,有深克隆和浅克隆之分,若克隆对象中存在引用类型的属性深克隆会将此属性完全拷贝一份,而浅克隆仅仅...

    Java深复制与浅复制.doc

    4. **处理引用类型字段**:对于引用类型的字段,如果需要深复制,需要手动进行复制或使用序列化、反序列化等方法来实现。 以下是一个简单的例子,展示了如何实现深复制: ```java class Student implements ...

    Java经典编程源码基础例程300.zip

    实例055 Java对象的浅克隆 80 实例056 Java对象的深克隆 82 实例057 序列化与对象克隆 84 实例058 深克隆效率的比较 87 第7章 面向对象进阶 89 实例059 经理与员工的差异 90 实例060 重写父类中的方法 92 实例061 ...

    java Clone

    如果对象的成员变量是不可克隆的(如`final`字段或不可克隆的第三方类),则可能需要采用其他策略,比如序列化和反序列化,或者手动创建新对象并复制属性。 总之,Java的`clone`机制提供了复制对象的能力,通过实现...

    24设计模式-原型模式1

    克隆分为两种类型:浅克隆和深克隆。默认的`clone()`方法执行浅克隆,这意味着新创建的对象将拥有原始对象的所有属性值,但引用的对象不会被复制,而是共享相同的引用。如果需要复制引用对象,就需要重写`clone()`...

Global site tag (gtag.js) - Google Analytics