Java基础:序列化(Serializable)与反序列化

在学习IO中的ObjectOutputStream和ObjectInputStream时,会涉及到序列化和反序列化的应用,那么它们是什么?

一、概念

序列化:把对象转换为字节序列的过程,叫做对象的序列化。

反序列化:把字节序列恢复为对象的过程,叫做对象的反序列化。

二、作用

主要有两种用途:

1.把对象的字节序列永久保存在硬盘中,也就是把内存中的数据(对象)持久化处理。

2.可以在网络上传输对象的字符序列,对象不再局限于本地使用。

无论那种用途,实际上都是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。这是java提供的一种保存对象状态的机制。

三、应用

在开头有提到,在java.io包中有两个序列化对象的类,分别为:ObjectOutputStream将对象写入字节流,ObjectInputStream将字节流重构为对象。

需要注意的是,被序列化的对象必须要实现Serializable或者Externalizable接口。

例子1:(为了方便阅读,异常都做抛处理):

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 import java.io.Serializable;
 7
 8 public class Test {
 9     public static void main(String[] args) throws Exception{
10         Person p = new Person("zhangsan",20);
11         serializePerson(p);
12         Person p1 = deserializePerson();
13         System.out.println(p1);        //结果打印zhangsan:20。
14     }
15
16 //    序列化
17     private static void serializePerson(Object obj) throws Exception {
18         ObjectOutputStream out= new ObjectOutputStream(new FileOutputStream(new File("c:\\obj.txt")));
19         out.writeObject(obj);
20         System.out.println("序列化成功");
21         out.close();
22     }
23
24 //    反序列化
25     private static Person deserializePerson() throws Exception {
26         ObjectInputStream in = new ObjectInputStream(new FileInputStream("c:\\obj.txt"));
27         Person p1 = (Person)in.readObject();
28         System.out.println("反序列化成功");
29         in.close();
30         return p1;
31     }
32
33 }
34
35
36 class Person implements Serializable {
37 //    注意,如果不指定serialVersionUID,序列化时会按默认方式进行,也会产生serialVersionUID。
38 //    但是如果后来有修改类中代码,序列化产生的serialVersionUID也会改变,这时反序列化就会失败,发生异常。
39     private static final long serialVersionUID = 1L;
40     private String name;
41     private int age;
42     Person() {
43         System.out.println("空参数构造函数");
44     }
45     public Person(String name, int age) {
46         System.out.println("有参数构造函数");
47         this.name = name;
48         this.age = age;
49     }
50
51     public String toString() {
52         return name+":"+age;
53     }
54 }

以上代码运行结果为:

有参数构造函数
序列化成功
反序列化成功
zhangsan:20

从结果可以看出,反序列化时,并没用通过Person类的构造函数,而是根据序列化的数据创建Person对象的。

要注意的是,默认serialVersionUID的取值是Java运行时,根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。

显式定义serialVersionUID可以实现两种目的:

1.若想不同版本的类(类有做过修改)序列化后,都能成功反序列化(兼容),就需要确保类的不同版本的类具有相同的serialVersionUID;

2.若不想不同版本的类序列化后还能成功反序列化,就让不同版本的类具有不同的serialVersionUID。

例子2:

先序列化:

 1 public class TestSerialze {
 2     public static void main(String[] args) throws Exception{
 3         Person p = new Person("zhangsan",20);
 4         serializePerson(p);
 5     }
 6
 7 //    序列化
 8     private static void serializePerson(Object obj) throws Exception {
 9         ObjectOutputStream out= new ObjectOutputStream(new FileOutputStream(new File("c:\\obj.txt")));
10         out.writeObject(obj);
11         System.out.println("序列化成功");
12         out.close();
13     }
14 }
15
16
17 class Person implements Serializable {
18 //    注意,如果不指定serialVersionUID,序列化时会按默认方式进行,也会产生serialVersionUID。
19 //    但是如果修改类中内容后,序列化产生新的serialVersionUID,跟原来不一样,这时反序列化就会失败,发生异常。
20     private static final long serialVersionUID = 1L;
21     private String name;
22     private int age;
23 //    静态成员属于类,不能被序列化。
24     private static int count;
25 //    瞬态也不能被序列化。
26     transient private int key;
27
28     Person() {
29         System.out.println("空参数构造函数");
30     }
31     public Person(String name, int age) {
32         System.out.println("有参数构造函数");
33         this.name = name;
34         this.age = age;
35         count++;
36         key++;
37     }
38
39     public String toString() {
40         return name+":"+age+"..."+count+"..."+key;
41     }
42 }

后反序列化:

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class TestDeserialze {
    public static void main(String[] args) throws Exception{
        Object obj = deserializeObject();
        System.out.println(obj);
    }

    private static Object deserializeObject() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("c:\\obj.txt"));
        Object obj = in.readObject();
        System.out.println("反序列化成功");
        in.close();
        return obj;
    }
}

反序列化得到的结果是:

反序列化成功
zhangsan:20...0...0

以上可以看出被static和transient修饰的成员变量无法被序列化。

时间: 2024-10-27 07:43:56

Java基础:序列化(Serializable)与反序列化的相关文章

Java序列化(Serializable)与反序列化

序列化是干什么的 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保 存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化. 什么情况下需要序列化 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候: 当你想用套接字在网络上传送对象的时候: 当你想通过RMI传输对象的时候: 序列化的几种方式 在Java中socket传输数据时,数据类型往往比较难

Java 的序列化Serializable接口介绍及应用

常看到类中有一串很长的 如 private static final long serialVersionUID = -4667619549931154146L;的数字声明.这些其实是对此类进行序列化的,那为何要进行序列化呢?下面参照网络及jdk说明,进行学习一下: 理解: serialVersionUID 用来表明类的不同版本间的兼容性 简单的说,Java的序列化是通过在运行时判断类的serialversionUID来验证版本的一致性的.在进行序列化时,jvm会把传来的字节流中的serialv

JAVA 对象序列化——Serializable

1.序列化是干什么的?       简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化. 2.什么情况下需要序列化       a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候:    b)当你想用套接字在网络上传送对象的时候:    c)当你想通过RMI传输对象的时候: 3.当对一个对象

Java基础——序列化

Java的“对象序列化”能将一个实现了Serialiable接口(标记接口,没有任何方法)的对象转化为一组byte,这样日后要用到这个对象的时候,就能把这些byte数据恢复出来,并据此重新构建那个对象.这一点在跨网络的环境下也是如此,这就意味着序列化机制能自动补偿操作系统方面的差异.也就是说,可以在Windows机器上创建一个对象,序列化之后,再通过网络传到UNIX机器上,最后再那里重建该对象,不用担心在不同平台上数据是怎么表示的,以及byte顺序怎么样,或者 别的什么细节. 要想序列化对象,必

一天一个Java基础——序列化

1.概念 Java的“对象序列化”能将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,能把这些byte数据恢复出来,并据此重新构建那个对象. 对象序列化能实现“轻量级persistence(lightweight persistence)”.所谓persistence,是指对象的生命周期不是由程序是否运行决定的,在程序的两次调用之间对象仍然还活着.通过“将做过序列化处理的对象写入磁盘,等到程序再次运行的时候再把它读出来”,可以达到persistence

java基础 序列化

参考文档:序列化与反序列化:http://kb.cnblogs.com/page/515982/jdk中的序列化api:http://blog.csdn.net/abc6368765/article/details/51365838jdk中如何序列化:http://www.cnblogs.com/redcreen/articles/1955307.html 什么是序列化&为什么要序列化序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当

【Java基础】序列化与反序列化深入分析

一.前言 复习Java基础知识点的序列化与反序列化过程,整理了如下学习笔记. 二.为什么需要序列化与反序列化 程序运行时,只要需要,对象可以一直存在,并且我们可以随时访问对象的一些状态信息,如果程序终止,那么对象是肯定不会存在的,但是有时候,我们需要再程序终止时保存对象的状态信息,之后程序再次运行时可以重新恢复到之前的状态,如,玩家玩游戏退出时,需要保存玩家的状态信息(如等级.装备等等),之后玩家再此登入时,必须要恢复这些状态信息.我们可以通过数据库手段来达到这个保存状态的目的,在Java中,我

Java基础学习总结——Java对象的序列化和反序列化

一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些s

Java基础知识强化之IO流笔记65:序列化流 和 反序列化流

1. 什么是 序列化 和 反序列化 ?     序列化 (Serialization):将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象.一般的格式是与平台无关的二进制流,可以将这种二进制流持久保存在磁盘上,也可以通过网络将这种二进制流传输到另一个网络结点.  反序列化(Anti Serialization ):是指把这种二进制流数据还原成对象. 2. 序列化流 和 反序列化

使用Serializable接口进行JAVA的序列化和反序列化

OBJECT STREAMS – SERIALIZATION AND DESERIALIZATION IN JAVA EXAMPLE USING SERIALIZABLE INTERFACE Hitesh Garg | November 7, 2014 | io | 9 Comments In the previous java tutorials I have discussed about basic of java streams, byte streams, then a modifie