`
sgl124764903
  • 浏览: 171035 次
  • 性别: Icon_minigender_1
  • 来自: 邯郸
社区版块
存档分类
最新评论

java序列化一(转)

阅读更多

下面和大家分享的是java序列化的一些基础知识,希望能够带给大家帮助。

1 Java 序列化技术概述

Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方

把该Byte 流里的数据读出来。重新构造一个相同的对象。这种机制允许你将对象通过网络

进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的序列化机制是RMI、

EJB、JNNI等技术的技术基础。

1.1 序列化技术基础

并非所有的Java 类都可以序列化,为了使你指定的类可以实现序列化,你必须使该类

实现如下接口:

java.io.Serializable

需要注意的是,该接口什么方法也没有。实现该类只是简单的标记你的类准备支持序列

化功能。我们来看如下的代码:

/**

* 抽象基本类,完成一些基本的定义

*/

public abstract class Humanoid

{

protected int noOfHeads;

private static int totalHeads;

public Humanoid()

{

this(1);

}

public Humanoid(int noOfHeads)

{

如何正确的使用Java序列化技术 技术研究系列

if (noOfHeads > 10)

throw new Error("Be serious. More than 10 heads?!");

this.noOfHeads = noOfHeads;

synchronized (Humanoid.class)

{

totalHeads += noOfHeads;

}

}

public int getHeadCount()

{

return totalHeads;

}

}

该类的一个子类如下:

/**

* Humanoid的实现类,实现了序列化接口

*/

import java.io.*;

public class Person extends Humanoid

implements java.io.Serializable

{

private String lastName;

private String firstName;

private transient Thread workerThread;

private static int population;

public Person(String lastName, String firstName)

{

this.lastName = lastName;

this.firstName = firstName;

synchronized (Person.class)

{

population++;

}

}

public String toString()

{

return "Person " + firstName + " " + lastName;

}

static synchronized public int getPopulation()

{

return population;

}

}

1.2 对象的序列化及反序列化

上面的类Person 类实现了Serializable 接口,因此是可以序列化的。我们如果要把一个

可以序列化的对象序列化到文件里或者数据库里,需要下面的类的支持:

java.io.ObjectOutputStream

如何正确的使用Java序列化技术 技术研究系列

下面的代码负责完成Person类的序列化操作:

/**

* Person的序列化类,通过该类把Person写入文件系统里。

*/

import java.io.*;

public class WriteInstance

{

public static void main(String [] args) throws Exception

{

if (args.length != 1)

{

System.out.println("usage: java WriteInstance file");

System.exit(-1);

}

FileOutputStream fos = new FileOutputStream(args[0]);

ObjectOutputStream oos = new ObjectOutputStream(fos);

Person p = new Person("gaoyanbing", "haiger");

oos.writeObject(p);

}

}

如果我们要序列化的类其实是不能序列化的,则对其进行序列化时会抛出下面的异常:

java.io.NotSerializableException

当我们把Person 序列化到一个文件里以后,如果需要从文件中恢复Person 这个对象,

我们需要借助如下的类:

java.io.ObjectInputStream

从文件里把Person类反序列化的代码实现如下:

/**

* Person的反序列化类,通过该类从文件系统中读出序列化的数据,并构造一个

* Person对象。

*/

import java.io.*;

public class ReadInstance

{

public static void main(String [] args) throws Exception

{

if (args.length != 1)

{

System.out.println("usage: java ReadInstance filename");

System.exit(-1);

}

FileInputStream fis = new FileInputStream(args[0]);

ObjectInputStream ois = new ObjectInputStream(fis);

Object o = ois.readObject();

如何正确的使用Java序列化技术 技术研究系列

System.out.println("read object " + o);

}

}

1.3 序列化对类的处理原则

并不是一个实现了序列化接口的类的所有字段及属性都是可以序列化的。我们分为以下

几个部分来说明:

u 如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则

其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接

口,则该类的父类所有的字段属性将不会序列化。

u 如果该类的某个属性标识为static类型的,则该属性不能序列化;

u 如果该类的某个属性采用transient关键字标识,则该属性不能序列化;

需要注意的是,在我们标注一个类可以序列化的时候,其以下属性应该设置为transient

来避免序列化:

u 线程相关的属性;

u 需要访问IO、本地资源、网络资源等的属性;

u 没有实现可序列化接口的属性;(注:如果一个属性没有实现可序列化,而我们又

没有将其用transient 标识, 则在对象序列化的时候, 会抛出

java.io.NotSerializableException 异常)。

1.4 构造函数和序列化

对于父类的处理,如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有

参数的构造函数)。为什么要这样规定呢?我们来看实际的例子。仍然采用上面的Humanoid

和Person 类。我们在其构造函数里分别加上输出语句:

/**

* 抽象基本类,完成一些基本的定义

*/

public abstract class Humanoid

{

protected int noOfHeads;

private static int totalHeads;

public Humanoid()

{

this(1);

System.out.println("Human's default constructor is invoked");

}

public Humanoid(int noOfHeads)

{

if (noOfHeads > 10)

throw new Error("Be serious. More than 10 heads?!");

如何正确的使用Java序列化技术 技术研究系列

this.noOfHeads = noOfHeads;

synchronized (Humanoid.class)

{

totalHeads += noOfHeads;

}

}

public int getHeadCount()

{

return totalHeads;

}

}

/**

* Humanoid的实现类,实现了序列化接口

*/

import java.io.*;

public class Person extends Humanoid

implements java.io.Serializable

{

private String lastName;

private String firstName;

private transient Thread workerThread;

private static int population;

public Person(String lastName, String firstName)

{

this.lastName = lastName;

this.firstName = firstName;

synchronized (Person.class)

{

population++;

}

System.out.println("Person's constructor is invoked");

}

public String toString()

{

return "Person " + firstName + " " + lastName;

}

static synchronized public int getPopulation()

{

return population;

}

}

在命令行运行其序列化程序和反序列化程序的结果为:

如何正确的使用Java序列化技术 技术研究系列

可以看到,在从流中读出数据构造Person对象的时候,Person 的父类Humanoid的默认

构造函数被调用了。当然,这点完全不用担心,如果你没有给父类一个默认构造函数,则编

译的时候就会报错。

这里,我们把父类Humanoid做如下的修改:

/**

* 抽象基本类,完成一些基本的定义

*/

public class Humanoid implements java.io.Serializable

{

protected int noOfHeads;

private static int totalHeads;

public Humanoid()

{

this(1);

System.out.println("Human's default constructor is invoked");

}

public Humanoid(int noOfHeads)

{

if (noOfHeads > 10)

throw new Error("Be serious. More than 10 heads?!");

this.noOfHeads = noOfHeads;

synchronized (Humanoid.class)

{

totalHeads += noOfHeads;

}

}

public int getHeadCount()

{

return totalHeads;

}

}

我们把父类标记为可以序列化, 再来看运行的结果:

如何正确的使用Java序列化技术 技术研究系列

可以看到,在反序列化的时候,如果父类也是可序列化的话,则其默认构造函数也不会

调用。这是为什么呢?

这是因为Java 对序列化的对象进行反序列化的时候,直接从流里获取其对象数据来生

成一个对象实例,而不是通过其构造函数来完成,毕竟我们的可序列化的类可能有多个构造

函数,如果我们的可序列化的类没有默认的构造函数,反序列化机制并不知道要调用哪个构

造函数才是正确的。

1.5 序列化带来的问题

我们可以看到上面的例子,在Person 类里,其字段population 很明显是想跟踪在一个

JVM里Person类有多少实例,这个字段在其构造函数里完成赋值,当我们在同一个JVM 里

序列化Person 并反序列化时,因为反序列化的时候Person 的构造函数并没有被调用,所以

这种机制并不能保证正确获取Person在一个JVM的实例个数,在后面的部分我们将要详细

探讨这个问题及给出比较好的解

分享到:
评论

相关推荐

    ####这是一篇对python的详细解析

    python

    菜日常菜日常菜日常菜日常

    菜日常菜日常菜日常菜日常

    VB学生档案管理系统设计(源代码+论文).rar

    计算机专业毕业设计VB精品论文资源

    电商到底怎么做?淘系电商三维经营心法(59节课)-课程网盘链接提取码下载 .txt

    课程内容: 10-经营常见4大循环-被资本绑架思维.mp4 11-落地中的47个坑-产品坑.mp4 12-落地中的47个坑-一把手坑.mp4 13-落地中的47个坑-迷信坑.mp4 14-落地中的47个坑-缺乏坑.mp4 15-落地中的47个坑-团队坑.mp4 16-电商经营常见导致的10种挂法.mp4 18-淘系电商干法介绍.mp4 19-淘系电商的特点.mp4 20-淘系买家购物场景.mp4 21-淘系干法-标品.mp4 22-淘系电商干法-半标品.mp4 23-答疑.mp4 25-3类7种常见“干法”模型.mp4 26-6类产品日常运营报表.mp4 27-6类产品日常运营报表-高客单价店铺.mp4 28-6类产品运营报表-低客单价.mp4 29-6类产品运营报表-爆款数据模型季节性商品.mp4 2-前言.mp4 30-6类产品日常运营-标品.mp4 31-6类产品日常运营报表-非标品.mp4 32-6类产品日常运营报表-全店客服.mp4 33-执行就是一条:运营公式.mp4 35-搜索算法逻辑.mp4 36-2024年词层分层“激

    grpcio-1.63.0-cp312-cp312-linux_armv7l.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    labview使用DAQ采集数据时显示设备标识符无效

    当安装好NI-DAQmx后仍然无法运行采集程序,并且显示显示设备标识符无效,则需要添加虚拟采集设备。

    WX小程序源码无后台gank

    WX小程序源码无后台gank提取方式是百度网盘分享地址

    debugpy-1.6.4-py2.py3-none-any.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    VB中大迅通合同统计系统(论文+源代码).rar

    计算机专业毕业设计VB精品论文资源

    大学生毕业答辨ppt免费模板【不要积分】下载可编辑可用(144).zip

    大学生毕业答辨ppt免费模板【不要积分】下载可编辑可用(144).zip

    grpcio-1.46.5-cp36-cp36m-musllinux_1_1_i686.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    debugpy-1.0.0b2-cp35-cp35m-manylinux1_x86_64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    grpcio-1.45.0-cp310-cp310-musllinux_1_1_i686.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    基于C++及Qt5开发的图片自动矢量化软件+高分辨率图像去噪+自动矢量化为svg/shp矢量图+不限定颜色种类和数量(高分项目)

    基于C++及Qt5开发的图片自动矢量化软件+高分辨率图像去噪+自动矢量化为svg/shp矢量图+不限定颜色种类和数量,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于C++及Qt5开发的图片自动矢量化软件+高分辨率图像去噪+自动矢量化为svg/shp矢量图+不限定颜色种类和数量,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于C++及Qt5开发的图片自动矢量化软件+高分辨率图像去噪+自动矢量化为svg/shp矢量图+不限定颜色种类和数量,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 项目简介: 基于Qt5开发的图片自动矢量化软件,可对高分辨率图像进行去噪、自动矢量化为svg/shp矢量图,不限定颜色种类和数量,且不会产生缝隙,比adobe illustrator更好用

    debugpy-1.6.6-cp37-cp37m-win32.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    debugpy-1.6.5-cp39-cp39-win_amd64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    grpcio-1.48.2-cp310-cp310-musllinux_1_1_x86_64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    基于多种编程语言的新闻推荐系统设计源码

    本项目是基于多种编程语言的新闻推荐系统设计源码,包含29个文件,其中包括20个Python源文件、3个JavaScript文件、2个SQL文件、2个HTML文件、1个CSS样式文件和1个TXT文本文件。系统专注于提供新闻推荐功能,支持内容聚合、用户行为分析等功能,为用户提供了一个稳定、高效的新闻推荐平台。

    基于Java的智慧车位管理系统后端设计源码

    本项目是基于Java的智慧车位管理系统后端设计源码,包含89个文件,其中包括70个Java源文件、12个XML配置文件、1个Gitignore文件、1个Dockerfile文件、1个LICENSE文件、1个Markdown文档、1个YAML配置文件和1个SQL文件。系统专注于提供智慧车位管理功能,支持车位信息管理、停车记录查询等功能,为用户提供了一个稳定、高效的智慧车位管理系统。

    20231108陈震浩《Python程序设计》实验四报告

    20231108陈震浩《Python程序设计》实验四报告

Global site tag (gtag.js) - Google Analytics