Java序列化、反序列化和单例模式
学习JAVA的时候,特别是涉及到网络编程时,我们时常让我们的实体类实现一个接口
public class Entity implements Serializable{ }
这样子我们可以通过输入输出流ObjectOutputStream和ObjectInputStream写入或读取该对象。所以,简单来说,序列化就是把对象转换为字节数据流,反序列化就是把字节序列流转成相应的Java对象。使用序列化的最常用的两个场景:
1、需要把对象信息存储到磁盘文件中的时候,比如大量用户登录的Session信息
2、需要把对象信息通过网络传送的时候,需要传送字节流
实现java.io.Serializable接口之后,编辑器会给出警告,让你给出一个属性的定义:
private static final long serialVersionUID = 1L;
我们可以简单的认为,这是一个“类版本”的表示,不同的编辑器可能会对同一个类给出不同的值,类文件的细小改动也可能会产生不同的值,因为这个值在类变更之后起到了代码兼容的作用,一般规则如下:
1、两个不同版本的类,如果serialVersionUID相同,则说明反序列化兼容,以现有版本为模板反序列化
2、两个不同版本的类,如果serialVersionUID不同,说明反序列化不兼容,反序列化会失败
因此,我们的开发过程中,建议显示定义该值,并给以明确的定义,以方便兼容性判断。
下面代码示例,首先定义一个可序列化的实体对象:
package com.minlz.serialize; import java.io.Serializable; /** * @author minliangzhi * @date 2016年8月30日 */ public class Person implements Serializable { private static final long serialVersionUID = 20160830001L; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
然后给出一个序列化和反序列化的方法:
public static void main(String[] args) throws Exception { Person p1 = new Person(); p1.setName("Bruce Min"); p1.setAge(25); System.out.println("p1: " + p1.toString()); /** 序列化 */ ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(byteOut); objOut.writeObject(p1); /** 反序列化 */ ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream objIn = new ObjectInputStream(byteIn); Person p2 = (Person)objIn.readObject(); System.out.println("p2: " + p2.toString()); }
显示的结果是:
p1: Person [name=Bruce Min, age=25] p2: Person [name=Bruce Min, age=25]
通过上面的实例,大概对序列化和反序列化进行了介绍,需要注意的是,通过反序列获得对象不是原来的对象,即不满足“==”为真的情况,因为,如果我们是序列化一个单例实例的话,就会违反了单例模式的规定(虽然隐藏了单例的构造函数,但是JVM可以通过特殊手段,如反射来构造出对象)。实例如下:
单例类:
package com.minlz.serialize; import java.io.Serializable; /** * @author minliangzhi * @date 2016年8月30日 */ public class Singleton implements Serializable { private static final long serialVersionUID = 1L; private static Singleton singleton; private Singleton() { } public synchronized static Singleton getInstance() { if(null == singleton) { singleton = new Singleton(); } return singleton; } }
序列化和反序列化的代码:
public static void main(String[] args) throws Exception { Singleton s1 = Singleton.getInstance(); System.out.println(s1); /** 序列化 */ ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(byteOut); objOut.writeObject(s1); /** 反序列化 */ ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream objIn = new ObjectInputStream(byteIn); Singleton s2 = (Singleton)objIn.readObject(); System.out.println(s2); }
测试结果:
com.minlz.serialize.Singleton@47abfd68 com.minlz.serialize.Singleton@514ae5cd
可以容易看出来,两个对象不是同一个对象,解决方法是什么呢?
我们在Singleton类中增加一个方法:
public Object readResolve(){ return getInstance(); }
发现测试结果是:
com.minlz.serialize.Singleton@8523ca2 com.minlz.serialize.Singleton@8523ca2
两个对象一致了,所以当面临单例模式实例化的时候,需要实现public Object readResolve()方法,并返回单例实例,就能实现序列化和反序列化对象一致。
Java序列化、反序列化和单例模式的更多相关文章
- java序列化反序列化深入探究
When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想 ...
- java序列化反序列化深入探究(转)
When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想 ...
- 初尝Java序列化/反序列化对象
看个类: package com.wjy.bytes; import java.io.Serializable; public class ObjTest implements Serializabl ...
- java序列化/反序列化之xstream、protobuf、protostuff 的比较与使用例子
目录 背景 测试 环境 工具 说明 结果 结论 xstream简单教程 准备 代码 protobuf简单教程 快速入门 下载.exe编译器 编写.proto文件 利用编译器编译.proto文件生成ja ...
- Java序列化反序列化对象流ObjectInputStream、ObjectOutputStream
使用Person类作为Object进行示范 注意:Object要能被写入流需要实现Serializable接口 存储的文件后缀名为.ser 示范Person类 import java.io.Seria ...
- Java——序列化 反序列化
记录一下: 先粘两个比较繁琐的方法: put: public void putSerializableObject(String key, Object value, int expireTime) ...
- Java 序列化 反序列化 历史版本处理
直接引用 http://www.cnblogs.com/xdp-gacl/p/3777987.html
- Java 序列化 序列化与单例模式 [ 转载 ]
Java 序列化 序列化与单例模式 [ 转载 ] @author Hollis 本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏. 单例模式,是设计 ...
- Serializable详解(1):代码验证Java序列化与反序列化
说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...
- Java 序列化与反序列化
1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频. ...
随机推荐
- 各种Android手机Root方法
Root的介绍 谷歌的android系统管理员用户就叫做root,该帐户拥有整个系统至高无上的权利,它可以访问和修改你手机几乎所有的文件,只有root才具备最高级别的管理权限.我们root手机的过程 ...
- 常用js函数封装
see them... // 获取网址的get参数 var GET = function(name) { var reg = new RegExp("(^|&)" + na ...
- 【java回调】java两个类之间的回调函数传递
背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...
- angular 自定义指令 directive transclude 理解
项目中断断续续的用了下angular,也没狠下心 认真的学习.angular 特别是自定义指令这块 空白. transclude 定义是否将当前元素的内容转移到模板中.看解释有点抽象. 看解释有点抽象 ...
- Oracle 文件的导入与导出
说明:本机使用的是32位oracle,使用的方法是plsql导入与导出 1.导出数据步骤. 1)登陆上plsql后在工具里选择导出用户对象,选择上所有的表在选择保存的路径.点击导出就可以了. 2)上边 ...
- Java基础高级一(正则表达式)
1.正则语法:元字符,量词,范围,组,属性 2.String类常用正则方法split,indexOf,replaceAll 3.Java正则类Pattern,Match而的使用 1.String常用方 ...
- JS学习进阶中 come on!
1,定义新的属性来扩展对象 新方法:defineProperty() 实例: var data = {}: Object.defineProperty(data,"type",{ ...
- 关于计算机改名无法连接TFS的问题
今天重新导入了两台服务器, 修改了机器名,结果VS2012链接TFS报错 --------------------------- Microsoft Visual Studio ----------- ...
- 使用java读取文件夹中文件的行数
使用java统计某文件夹下所有文件的行数 经理突然交代一个任务:要求统计某个文件夹下所有文件的行数.在网上查了一个多小时没有解决.后来心里不爽就决定自己写一个java类用来统计文件的行数,于是花了两个 ...
- access基本操作(c#操作,远程连接,执行sql,加密,备份)
前言 最近项目用到了access,是的就是access,工作在桌面型的小数据库应用还是会用到的,如果你确定永远不会遇到access的操作,请忽略此篇文章 1.vs配置access 既然是数据库,就少不 ...