Serizlizable

版权声明:本文为博主原创文章,未经博主允许不得转载。
Serizlizable 作用
对于一个存在于Java虚拟机中的对象来说,其内部的状态只保持在内存中。JVM停止之后,这些状态就丢失了。在很多情况下,对象的内部状态是需要被持久化下来的。提到持久化,最直接的做法是保存到文件系统或是数据库之中。比如:对象关系映射(Object-relational mapping)。对象序列化机制(object serialization)是Java语言内建的一种对象持久化方式,可以很容易的在JVM中的活动对象和字节数组(流)之间进行转换。除了可以很简单的实现持久化之外,另外序列化机制的另外一个重要用途是在远程方法调用中,用来对开发人员屏蔽底层实现细节。
基本的对象序列化
待序列化的Java类只需要实现Serializable接口即可。实际的序列化和反序列化工作是通过ObjectOuputStream和ObjectInputStream来完成的。ObjectOutputStream的writeObject方法可以把一个Java对象写入到流中,ObjectInputStream的readObject方法可以从流中读取一个Java对象。在写入和读取的时候,虽然用的参数或返回值是单个对象,但实际上操纵的是一个对象图,包括该对象所引用的其它对象,以及这些对象所引用的另外的对象。Java会自动帮你遍历对象图并逐个序列化。除了对象之外,Java中的基本类型和数组也是可以通过 ObjectOutputStream和ObjectInputStream来序列化的。
序列化时的对象替换
可能会希望在序列化的时候使用另外一个对象来代替当前对象。其中的动机可能是当前对象中包含了一些不希望被序列化的域。个订单系统中需要把订单的相关信息序列化之后,通过网络来传输。订单类Order引用了客户类Customer。在默认序列化的情况下,Order类对象被序列化的时候,其引用的Customer类对象也会被序列化,这可能会造成用户信息的泄露。
Private static class OrderReplace implements Serializable{
Private static final long serialVersionUID=47832438;
Private String orderId;
Public OrderReplace(Order order){
This.orderId = order.getId();
}
Private Object readResolve(){
//根据orderId查找Order 对象并返回。
}
Public Object writeReplace(){
Return new OrderReplace(this);
}
}
这个替换对象类OrderReplace只保存了Order的ID。在Order类的writeReplace方法中返回了一个OrderReplace对象。这个对象会被作为替代写入到流中。同样的,需要在OrderReplace类中定义一个readResolve方法,用来在读取的时候再转换回 Order类对象。这样对调用者来说,替换对象的存在就是透明的。
序列化和对象创建
在通过ObjectInputStream的readObject方法读取到一个对象之后,这个对象是一个新的实例,但是其构造方法是没有被调用的,其中的域的初始化代码也没有被执行。调用者并不知道对象是通过一般的new操作符来创建的,还是通过反序列化所得到的。解决的办法就是在类的readObject方法里面,再执行所需的对象初始化逻辑。对于一般的Java类来说,构造方法中包含了初始化的逻辑。可以把这些逻辑提取到一个方法中,在readObject方法中调用此方法。
版本更新
把一个Java对象序列化之后,所得到的字节数组一般会保存在磁盘或数据库之中。在保存完成之后,有可能原来的Java类有了更新,比如添加了额外的域。这个时候从兼容性的角度出发,要求仍然能够读取旧版本的序列化数据。在读取的过程中,当ObjectInputStream发现一个对象的定义的时候,会尝试在当前JVM中查找其Java类定义。这个查找过程不能仅根据Java类的全名来判断,因为当前JVM中可能存在名称相同,但是含义完全不同的Java 类。这个对应关系是通过一个全局惟一标识符serialVersionUID来实现的。通过在实现了Serializable接口的类中定义该域,就声明了该Java类的一个惟一的序列化版本号。JVM会比对从字节数组中得出的类的版本号,与JVM中查找到的类的版本号是否一致,来决定两个类是否是兼容的。对于开发人员来说,需要记得的就是在实现了Serializable接口的类中定义这样的一个域,并在版本更新过程中保持该值不变。当然,如果不希望维持这种向后兼容性,换一个版本号即可。该域的值一般是综合Java类的各个特性而计算出来的一个哈希值。可以通过Java提供的serialver命令来生成。在Eclipse中,如果Java类实现了Serializable接口,Eclipse会提示并帮你生成这个serialVersionUID。
Eg:
public class Book implements Serializable {
//private static final long serialVersionUID = 5805574648076667828L;
String name="chenlly";
//int vale = 7;
//序列化写入文件
public void save() throws IOException {
FileOutputStream f = new FileOutputStream("d://book.bin");
ObjectOutputStream oos = new ObjectOutputStream(f);
oos.writeObject(this);
oos.close();
}
//反序列化从文件读取
public void read() throws IOException, ClassNotFoundException {
FileInputStream f = new FileInputStream("d://book.bin");
ObjectInputStream ois = new ObjectInputStream(f);
Book b = (Book) ois.readObject();
ois.close();
}
public static void main(String []args){
Book b = new Book();
try {
//序列化
b.save();
//读取
b.read();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果增加int vale = 7;,把b.save()注释掉,再次执行程序则会抛出如下异常。
java.io.InvalidClassException: cn.com.chenlly.Book; local class incompatible: stream classdesc serialVersionUID = -8127777334808352611, local class serialVersionUID = 6452469819260868051
java 默认情况下serialVersionUID是是综合Java类的各个特性而计算出来的一个哈希值。
两次的属性值一样导致serialVersionUID也不一样。
如果加上private static final long serialVersionUID = 5805574648076667828L则这个类都有一个唯一标识,两次的serialVersionUID不变。反序列化中还是不会报错。
如果把字符串改成int name=34; 执行逆-串行化操作时系统就不知道如何处理该值,显示出错误信息:java.io.InvalidClassException: cn.com.chenlly.Book; incompatible types for field name。
简而言之,如果文件中确实保存了所有必需的数据,那么仍有可能读取该文件,当然前提是必须处理好串行化的UID。
- 顶
- 2
- 踩
- 1
- 猜你在找
- 【直播】机器学习&数据挖掘7周实训--韦玮
- 【套餐】系统集成项目管理工程师顺利通关--徐朋
- 【直播】3小时掌握Docker最佳实战-徐西宁
- 【套餐】机器学习系列套餐(算法+实战)--唐宇迪
- 【直播】计算机视觉原理及实战--屈教授
- 【套餐】微信订阅号+服务号Java版 v2.0--翟东平
- 【直播】机器学习之矩阵--黄博士
- 【套餐】微信订阅号+服务号Java版 v2.0--翟东平
- 【直播】机器学习之凸优化--马博士
- 【套餐】Javascript 设计模式实战--曾亮
- 文章分类
- JSE(40)
- JEE(12)
- SSH(Struts/Spring/Hibernate)(11)
- Python(8)
- C(4)
- C++(5)
- assembly program(1)
- Linux/Ubuntu(18)
- Oracle Spatial(6)
- Oracle(4)
- MongoDB(2)
- GIS(18)
- JTS(6)
- GeoTools(2)
- ArcGIS(4)
- Data Structure_JAVA(33)
- Data Structure_C(8)
- RegEx(1)
- XML/JSON(4)
- WebService(4)
- Database(3)
- SQL(Structured Query Language)(4)
- Computer Network(4)
- UI(9)
- AS(Application Server)(3)
- CM(Configuration Management)(11)
- Soft Project(2)
- PM(Project Management)(5)
- lucene(0)
- hadoop(2)
- nutch(3)
- Design pattern(3)
- appfuse(2)
- 图像处理(2)
- 读书笔记(16)
- 年度总结(5)
- 成长过程(10)
- 经济学(5)
- 翻译(7)
- 杂感随笔(16)
- 最新评论
- 一位蜗牛程序员七年工作总结-2014
jiankeufo: 更清晰了
- 一位蜗牛程序员五年工作总结-2012
jiankeufo: 混脸熟
- 一位蜗牛程序员四年工作总结-2011
jiankeufo: 还通过了北航的考试。厉害啊
- 一位蜗牛程序员三年工作总结-2010
jiankeufo: 希望把每年阅读的书籍都列一下,哈哈,关注你了
- Spring通过@AspectJ方式实现AOP
u013086062: 学习了!
- Maven assembly实现自定义打包
cdl2008sky: @DEMONU:是的,打包的时候就是要过滤掉xml文件
- 道格拉斯-普克 Douglas-Peuker(DP算法)
cdl2008sky: @sxt_zls:http://www.csdn.net/tag/jts/downloadhttps...
- 道格拉斯-普克 Douglas-Peuker(DP算法)
cdl2008sky: @tingyu_99:http://www.csdn.net/tag/jts/downloadhtt...
- 一个简单的JSP分页代码
u014362204: 很好 好用
- Spring Annotation 详解
gpj331204181: java框架生成,www点javacoder点top,希望各位coder受益
Serizlizable的更多相关文章
- IO流 总结三
编码:字符串变成字节数组. 解码:字节数组变成字符串 String --> byte[]; str.getBytes(); byte --> String: new String(byt ...
- [Android]Parcelable encountered IOException writing serializable object (name = xxx)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- ConcurrentHashMap源码分析(一)
本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...
- 为什么很多类甚者底层源码要implements Serializable ?
为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...
- Android DevArt6:Android中IPC的六种方式
Android中IPC的六种方式 1.使用Bundle 最简单的进程间通信方式:Intent + Bundle: 支持三大组件:Activity.Service.BroadcastReceiver : ...
- java第七节 IO
/* *第七讲 IO/输入与输出 * * File类 * RandomAccessFile类 * 各种节点流类 * 字符编码 * 各种过滤流与包装类 * *File类 * File类是IO包中唯一代表 ...
- serilization 序列化 transient 不被序列化
Serizlizable 作用 对于一个存在于Java虚拟机中的对象来说,其内部的状态只保持在内存中.JVM停止之后,这些状态就丢失了.在很多情况下,对象的内部状态是需要被持久化下来的.提到持久化,最 ...
- java 序列化原来如此
上次面试的时候 ,如何实现java 类的序列化,当时感觉这个问题很简单,我的回答是实现serizlizable 接口就好了,可以实现对象的持久化,看了看书,原来这样: public class Ser ...
- java基础源码 (6)--ArrayListt类
原作出处:https://www.cnblogs.com/leesf456/p/5308358.html 简介: 1.ArrayList是一个数组队列,相当于动态数组.与java中的数组相比,它的容量 ...
随机推荐
- Mysql Left Join Where On
select t1.id,t2.idfrom t1left join t2 on t1.id = t2.id and t1.id>1 and t2.id<>3在mysql的left ...
- Java IO的应用之实现大文件复制
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827481.html 用IO进行文件复制,实质就是用FileInputStream链接要复制的文件,按一定规 ...
- 用pyenv和virtualenv搭建单机多版本python虚拟开发环境
作为主流开发语言, 用python 开发的程序越来越多. 方便的是大多linux系统里面都默认集成了python, 开发可以随时随地开始. 但有时候这也成为了一个短板, 比如说有时候我们需要开发和调试 ...
- 妙用Pixel bender执行复杂运算/普通数据运算 传递Vector数组
最近发现pixel bender有两个特殊点: 1.Input Image4,不单单可以用BitmapData来初始化,也可以用Vector.<Number>初始化. 2.ShaderJo ...
- 防止跨站请求伪造(CSRF)攻击 和 防重复提交 的方法的实现
CSRF的概念可以参考:http://netsecurity.51cto.com/art/200812/102951.htm 本文介绍的是基于spring拦截器的Spring MVC实现 首先配置拦截 ...
- python之函数用法get()
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法get() #http://www.runoob.com/python/att-dic ...
- Dubbo架构设计详解(转收藏)
转自:http://shiyanjun.cn/archives/325.html Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合 ...
- java+win7+eclipse+Maven+sikuli 配置总结---图形脚本语言
简介:Sikuli 是一种新颖的图形脚本语言,或者说是一种另类的自动化测试技术.它与我们常用的自动化测试技术(工具)有很大的区别. 关于配置,一直是一个问题,下面做个总体介绍,用sikuli也有几个月 ...
- 深度优化LNMP之PHP
PHP缓存加速介绍 1.操作码介绍及缓存原理 当客户端请求一个php程序时,服务器的PHP引擎会解析该PHP程序,并将其编译为特定的操作码文件(Operate Code,opcode)该文 ...
- Linux命令:用“dirs”、“pushd”、“popd”来操作目录栈
你可以将目录压入目录栈,也可以稍后将该目录弹出.在随后的示例中,将会用到以下三个命令: * dirs:显示目录栈 * pushd:将目录压入目录栈 * popd:将目录弹出目录栈 dirs命令显示当前 ...
目录视图
摘要视图
订阅

