java序列化详细解释

转载 2017年01月02日 21:12:47

Java 序列化Serializable详解(附详细例子)

1、什么是序列化和反序列化
Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。


2、什么情况下需要序列化 
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;

3、如何实现序列化

将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以序列化。


4、序列化和反序列化例子

如果我们想要序列化一个对象,首先要创建某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),然后将这些OutputStream封装在一个ObjectOutputStream中。这时候,只需要调用writeObject()方法就可以将对象序列化,并将其发送给OutputStream(记住:对象的序列化是基于字节的,不能使用Reader和Writer等基于字符的层次结构)。而反序列的过程(即将一个序列还原成为一个对象),需要将一个InputStream(如FileInputstream、ByteArrayInputStream等)封装在ObjectInputStream内,然后调用readObject()即可。

?
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
package com.sheepmu;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class MyTest implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String name="SheepMu";
    private int age=24;
    public static void main(String[] args)
    {//以下代码实现序列化
        try
        {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));//输出流保存的文件名为 my.out ;ObjectOutputStream能把Object输出成Byte流
            MyTest myTest=new MyTest();
            oos.writeObject(myTest);
            oos.flush();  //缓冲流
            oos.close(); //关闭流
        } catch (FileNotFoundException e)
        {       
            e.printStackTrace();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        fan();//调用下面的  反序列化  代码
    }
    public static void fan()//反序列的过程
    {   
         ObjectInputStream oin = null;//局部变量必须要初始化
        try
        {
            oin = new ObjectInputStream(new FileInputStream("my.out"));
        } catch (FileNotFoundException e1)
        {       
            e1.printStackTrace();
        } catch (IOException e1)
        {
            e1.printStackTrace();
        }     
        MyTest mts = null;
        try {
            mts = (MyTest ) oin.readObject();//由Object对象向下转型为MyTest对象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }    
         System.out.println("name="+mts.name);   
         System.out.println("age="+mts.age);   
    }
}
会在此项目的工作空间生成一个 my.out文件。序列化后的内容稍后补齐,先看反序列化后输出如下:

name=SheepMu
age=24

5、序列化ID

序列化 ID 在 Eclipse 下提供了两种生成策略,一个是固定的 1L,一个是随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具生成),在这里有一个建议,如果没有特殊需求,就是用默认的 1L 就可以,这样可以确保代码一致时反序列化成功。这也可能是造成序列化和反序列化失败的原因,因为不同的序列化id之间不能进行序列化和反序列化。


6.序列化前和序列化后的对象的关系

是 "=="还是equal? or 是浅复制还是深复制? 

答案:深复制,反序列化还原后的对象地址与原来的的地址不同

序列化前后对象的地址不同了,但是内容是一样的,而且对象中包含的引用也相同。换句话说,通过序列化操作,我们可以实现对任何可Serializable对象的”深度复制(deep copy)"——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,但是与其他流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,而且只要在同一流中,对象都是同一个。


7.静态变量能否序列化

若把上面的代码中的 age变量前加上 static ,输出任然是

name=SheepMu
age=24

但是看下面的例子:

?
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
package com.sheepmu;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyTest implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String name="SheepMu";
    private static int age=24;
    public static void main(String[] args)
    {//以下代码实现序列化
        try
        {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));//输出流保存的文件名为 my.out ;ObjectOutputStream能把Object输出成Byte流
            MyTest myTest=new MyTest();
            oos.writeObject(myTest);
            oos.flush();  //缓冲流
            oos.close(); //关闭流
        } catch (FileNotFoundException e)
        {       
            e.printStackTrace();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        fan();//调用下面的  反序列化  代码
    }
    public static void fan()
    {
        new MyTest().name="SheepMu_1";//!!!!!!!!!!!!!!!!重点看这两行 更改部分
          age=1;<span style="font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; ">//!!!!!!!!!!!!!!!!!!!重点看这两行 更改部分</span>
         ObjectInputStream oin = null;//局部变量必须要初始化
        try
        {
            oin = new ObjectInputStream(new FileInputStream("my.out"));
        } catch (FileNotFoundException e1)
        {       
            e1.printStackTrace();
        } catch (IOException e1)
        {
            e1.printStackTrace();
        }     
        MyTest mts = null;
        try {
            mts = (MyTest ) oin.readObject();//由Object对象向下转型为MyTest对象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }    
         System.out.println("name="+mts.name);   
         System.out.println("age="+mts.age);   
    }
}
输出结果为:

name=SheepMu
age=1
为何把最上面代码的age变量添上static 后还是反序列化出了24呢?而新的从新对变量赋值的代码,不是static的得到了序列化本身的值,而static的则得到的是从新附的值。原因: 序列化会忽略静态变量,即序列化不保存静态变量的状态。静态成员属于类级别的,所以不能序列化。即 序列化的是对象的状态不是类的状态。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。最上面添加了static后之所以还是输出24是因为该值是JVM加载该类时分配的值。注:transient后的变量也不能序列化,但是情况稍复杂,稍后开篇说。

8、总结:

a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

c) static,transient后的变量不能被序列化;

什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。

我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象...
  • coodlong
  • coodlong
  • 2016年03月09日 16:10
  • 1043

什么是java序列化,如何实现java序列化?或请解释Serializable接口的作用

首先要明确序列化的目的:     1.无论何种类型的数据,都是以二进制的形式在网络上传送,为了由一个进程把Java对象发送给另一个进程,需要把其转换为字节序列才能在网络上传送,把JAVA对象转换...
  • hustwht
  • hustwht
  • 2016年08月09日 00:19
  • 4192

Java反序列化漏洞详解

 Java反序列化漏洞从爆出到现在快2个月了,已有白帽子实现了jenkins,weblogic,jboss等的代码执行利用工具。本文对于Java反序列化的漏洞简述后,并对于Java反序列化的Po...
  • fengling59
  • fengling59
  • 2015年12月26日 21:25
  • 2533

Java Android常用术语英文简称及释义

干程序员这行实在是离不开英语,干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难。这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这些技术时往往受到语言障碍...
  • u014539135
  • u014539135
  • 2015年10月11日 21:59
  • 1189

Java序列化之关于Serializable的解释

先总结下:          Serializable接口 标记类可以被序列化(ObjectOutputStream)和反序列化(ObjectInputStream) 暴露了类的内存代表二进制...
  • XiaoBuHome
  • XiaoBuHome
  • 2016年05月02日 15:36
  • 820

java中序列化的serialVersionUID解释

serialVersionUID: 字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,...
  • hua00shao
  • hua00shao
  • 2014年11月23日 16:28
  • 201

java中序列化的serialVersionUID解释

serialVersionUID: 字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,...
  • cselmu9
  • cselmu9
  • 2014年12月13日 11:58
  • 620

java,什么是序列化,怎么实现序列化

转自:http://zhidao.baidu.com/question/202556575.html?qbl=relate_question_0&word=%CA%B2%C3%B4%CA%C7java...
  • zhangzhangjava
  • zhangzhangjava
  • 2016年04月12日 17:33
  • 3208

Java中的序列化Serialable高级详解

引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2014年02月08日 17:19
  • 30528

kernel中bluetooth的初始化

我们大家都知道,Android其实是基于linux之上进行运行的。在Android系统的运行之初,首先是kernel层的一系列的初始化。今天晓东就先和大家来简单分析一下在开机之后,kernel中和bl...
  • u011960402
  • u011960402
  • 2013年09月09日 15:04
  • 4037
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java序列化详细解释
举报原因:
原因补充:

(最多只允许输入30个字)