`
中国爪哇程序员
  • 浏览: 165023 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

序列化(三) 实例分析深入了解序列化

    博客分类:
  • java
阅读更多
一.什么是序列化和反序化
对象的序列化是把对象写到一个输出流中。反序列化从这把输入流读取一个对象。

二。为什么要序列化
(1) 把对象持久化到一个文件中。像我们在做单元测试的时候,对于构造好的数据,可以持久化到文件中,这样就不用再从数据库中读取,在数据库中的测试数据很容易被人篡改。
(2) 像RMI,SOCKET,HESSION 等进行网络传输对象的场合,要把对象转成流的形式传递给客户端。而客户端对于取的流(byte[])要进行反序列化。

三。如何进行序列化
实现Serializable 接口

四。Serializable的作用
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:

五。Serializable的使用说明
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 -- serialVersionUID 字段作为继承成员没有用处。数组类不能声明一个明确的 serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配 serialVersionUID 值的要求。

六。实例说明

序列化对象
import java.io.Serializable;

public class Customer implements Serializable{

	private static final long serialVersionUID = 1L;
	private Long userId;
	private String name;
	private String password;
	private int age;
	
	public Long getUserId() {
		return userId;
	}
	public void setUserId(Long userId) {
		this.userId = userId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}



测试代码:

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

		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:/objectFile.obj"));

		//创建对象
		Customer customer = new Customer();
		customer.setUserId(1L);
		customer.setName("张三");
		customer.setPassword("123");
		customer.setAge(10);
		
		// 序列化对象
		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);
		System.out.println("userId :"+obj3.getUserId());
		System.out.println("name :"+obj3.getName());
		System.out.println("password :"+obj3.getPassword());
		System.out.println("age :"+obj3.getAge());
		int obj4 = in.readInt();
		System.out.println("obj4=" + obj4);
		in.close();

	}


输出内容:
obj1=你好!
obj2=Thu Jun 23 23:26:11 CST 2011
obj3=user.Customer@c20e24
obj4=123

如果Customer去掉implements Serializable
则会抛出异常:
Exception in thread "main" java.io.NotSerializableException: user.Customer
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at demo.Demo1.main(Demo1.java:28)
只有实现seriliable接口才可以进行序列化

先序列化对象,并保存。
在返序列化的时候,修改
	private static final long serialVersionUID = 2L;

则会抛异常:
Exception in thread "main" java.io.InvalidClassException: user.Customer; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at demo.Demo1.main(Demo1.java:36)
原因就是serialVersionUID 有校验版本兼容性的作用。

七 transient 关键字
对于一些比较敏感信息,不希望被反序化,如password,可以加上transient ,则不会被反序列。其他未加transient属性信息都会正常序列化和反序化。

八 writeObject 和 readObject
像ObjectOutputStream和ObjectInputStream 两个类提供了序列化和反序列化的方法。当然也可以自己重写这两个方法。自己定义序列化和反序列化,这往往涉及一些加密和解密算法,记得大学有一门课程“信息论”的一门课程,提到了一系列加密算法,可以序列化产生的流做处理,保证网络传输的安全性。

分享到:
评论

相关推荐

    Pandas高级操作: 时间序列与数据可视化

    本资源集成了一系列深入探讨Pandas库高级功能的Python脚本,涵盖数据合并、重塑、分组聚合操作以及复杂的时间序列分析,并辅以直观的数据可视化实例。内容详尽、案例丰富,适合已具备Pandas基础知识的数据分析师、...

    JAVA基础课程讲义

    序列化/反序列化的步骤和实例 162 综合的序列化和反序列化练习 163 JAVA.IO包相关流对象用法总结(尚学堂1002班王鑫) 165 IO中其他常用类 165 File类 165 RandomAccessFile 166 思考作业 166 上机作业 166 提高课外...

    【Java设计模式】你对单例模式了解多少,一文深入探究

    不让第二步和第三步重排序-DoubleCheck方案二:基于类初始化-静态内部类饿汉式饿汉式与懒汉式最大区别序列化破坏单例模式原理枚举单例基于容器的单例模式基于TreadLocal线程单例源码分析-JDK源码分析-spring其他相关...

    Java思维导图xmind文件+导出图片

    理解通信协议传输过程中的序列化和反序列化机制 基于框架的RPC通信技术 WebService/ApacheCXF RMI/Spring RMI Hession 传统RPC技术在大型分布式架构下面临的问题 分布式架构下的RPC解决方案 Zookeeper ...

    Hadoop权威指南(中文版)2015上传.rar

    第16章 实例分析 Hadoop 在Last.fm的应用 Last.fm:社会音乐史上的革命 Hadoop a Last.fm 用Hadoop产生图表 Track Statistics程序 总结 Hadoop和Hive在Facebook的应用 概要介绍 Hadoop a Facebook 假想的使用情况...

    Hadoop权威指南 第二版(中文版)

    第16章 实例分析  Hadoop 在Last.fm的应用  Last.fm:社会音乐史上的革命  Hadoop a Last.fm  用Hadoop产生图表  Track Statistics程序  总结  Hadoop和Hive在Facebook的应用  概要介绍  Hadoop a Facebook...

    常规Java工具,算法,加密,数据库,面试题,源代码分析,解决方案.zip

    Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等...

    基于LSTM的情感分析程序实现源码

    【博文讲解链接:...整体来说,本文对LSTM模型和情感分析的相关技术进行了深入的探讨和分析,对自然语言处理领域的研究和实践具有重要意义。

    数据整理分析方法.docx

    1标准化分析 2 频率分布和外延分析 频率分布技术可以减少数据分析的工作量。这项技巧重点关注所要进一步调查的数据,辨别出不正确的数据值,还可以通过钻取技术做出更深层次的判断。 外延分析也可以帮助你查明问题...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    7.2 数据类型、对象、类和实例 301 7.2.1 类的起源 303 7.2.2 类的操作 303 7.2.3 术语 303 7.3 理解类 304 7.3.1 定义类 304 7.3.2 声明类的对象 305 7.3.3 访问类的数据成员 305 7.3.4 类的成员函数 307 ...

    SQL Server 2008数据库设计与实现

    第三部分深入探讨了SQL Server若干方面的技术细节,如数据保护、索引、并发访问等。通过将理论融入数据库实践,清晰地讲解了关系型数据库的设计原则,完整地展示了如何进行良好的关系型数据库设计,深入揭示了SQL ...

    最新Python3.5零基础+高级+完整项目(28周全)培训视频学习资料

    Json与pickle数据序列化 软件目录结构规范 本周作业 第5周 心灵分享 ATM存钱取钱案例剖析 模块定义、导入、优化详解 内置模块详解之time与datetime模块 内置模块详解之Range模块 内置模块详解之OS模块 内置模块...

    asp.net知识库

    泛型的序列化问题 .NET 2.0 泛型在实际开发中的一次小应用 C#2.0 Singleton 的实现 .Net Framwork 强类型设计实践 通过反射调用類的方法,屬性,字段,索引器(2種方法) ASP.NET: State Server Gems 完整的动态加载/卸载...

    antlr4权威指南

    ANTLR是一款强大的语法分析器生成工具,可用于读取、处理、执行和翻译结构化的文本或二进制文件。它被广泛应用于学术领域和工业生产实践,是众多语言、工具和框架的基石。Twitter搜索使用ANTLR进行语法分析,每天...

    基于双重粒化准则的邻域多粒度粗集快速约简算法

    为了有效降低属性约简计算过程中的迭代次数,实现邻域多粒度粗糙集模型的快速属性约简算法,基于双重粒化准则,深入分析不同属性子集序列和邻域半径对正域的影响,结合正域在属性子集和邻域半径共同作用下的单调性,提出...

    JBPM4工作流应用开始指南.rar

    170 第7章 流程变量 171 7.1 变量作用域 173 7.2 变量类型 174 7.3 变量的自动更新和序列化 175 7.4 例程:用变量去控制一个流程的运行 177 7.5 小结 179 第8章 流程脚本 182 8.1 Java统一表达式语言 182 8.1.1 语法...

    Java数据编程指南

    数据定义 基本数据操作 数据完整性 表达式 连接 合并 子查询 小结 附录B 序列化 简介 序列化 可串行化的接口 小结 附录C Java和分布式应用程序 分布式系统 分布式...

    疯狂JAVA讲义

    学生提问:为什么静态内部类实例方法也不能访问外部类的实例属性呢? 207 学生提问:接口里是否能定义内部接口? 208 6.7.3 使用内部类 208 学生提问:既然内部类是外部类的成员,是否可以为外部类定义子类,在...

Global site tag (gtag.js) - Google Analytics