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中的数组相比,它的容量 ...
随机推荐
- http 三次握手
1.三次握手 目的:主要规避由于网络阻塞,传输不畅等原因导致服务器端端口一直被占用,无法释放端口资源.(想想假设只要一次就建立连接,服务器响应后浏览器若是没收到数据,等待一段时间后,网络超时,浏览器重 ...
- 关于CBC for ios 加密要记
倒腾了接近半天,资料找了无数,最后是通过查看Android项目中的加密工具类,才弄明白,在这过程中掌握了一些知识点.比如: 问题1:关于PKCS7Padding和PKCS5Padding iOS中AE ...
- CentOS 7 安装php5.6,Nginx,Memcached环境及配置
安装php5.6版本以后不再需要安装Zend Guard,而是用yum命令安装php-opcache及php-pecl-apcu就可以有效的提高php执行速度. 1. 配置yum源 事先确认yum源的 ...
- excel快速访问工具栏和自定义选项卡
自定义选项卡: excel命令选项--自定义功能区--
- python之模块copy_reg(在python3中为copyreg,功能基本不变)
# -*- coding: utf-8 -*-#python 27#xiaodeng#python之模块copy_reg(在python3中为copyreg,功能基本不变) import copy_r ...
- OpenCV学习代码记录——轮廓(contour)检测
很久之前学习过一段时间的OpenCV,当时没有做什么笔记,但是代码都还在,这里把它贴出来做个记录. 代码放在码云上,地址在这里https://gitee.com/solym/OpenCVTest/tr ...
- Retrofit2完全教程
本文注目录: Retrofit入门 Retrofit注解详解 Gson与Converter RxJava与CallAdapter 自定义Converter 自定义CallAdapter 其它说明 前言 ...
- 利用组策略API 编辑GPO(Group Policy Object)
用windows自带的GPO Editor编辑修改,然后利用注册表监控器regFromApp监视注册表的改动,就知道某个策略修改了注册表的哪个字段了. 下面是禁止U盘访问的例子: #include ...
- sort.js
JavaScript to achieve the ten common sorting algorithm library 1 ; (function (global, factory) { // ...
- Maven实战——常用Maven插件介绍
maven nexus 库已上传了第三方jar,但就是用mvn compile下不到本地 回答于 2013-06-04 14:40 你是通过何种方式上传到nexus的? 有给pom文件吗? 如果是单纯 ...