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中的数组相比,它的容量 ...
随机推荐
- javascript用正則表達式检測username的合法性
在用户登录.用户注冊时经常须要对username如邮箱.手机号进行校验,一般经常使用表达式. 以下整理对邮箱和手机号的表达式校验: function checkUser(){ var userName ...
- Java读取并下载网络文件
CreateTime--2017年8月21日10:11:07 Author:Marydon import java.io.ByteArrayOutputStream; import java.io ...
- VREP中的力触觉设备接口(CHAI3D)
力反馈技术是一种新型的人机交互技术,它允许用户借助力反馈设备触碰.操纵计算机生成的虚拟环境中的物体,并感知物体的运动和相应的力反馈信息,实现人机力觉交互.虽然传统的鼠标.键盘.触摸屏等交互手段可以满足 ...
- 使用jquery的ajax提交文件上传
以前的项目大多的使用jquery的插件来进行文件上传,对于就只引用jquery而不使用插件来上传文件之前未有写过,最近项目里有写到和用到,就记录一下,以后方便查找. 提示:存在浏览器皆容问题,谨慎使用 ...
- django之创建第8-3个项目-数据库数据提取之高级操作
1.配置test2.html <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- django之创建第7-2个项目-url配置分离
1.urls.PY分离 # -*- coding: UTF-8 -*- from django.conf.urls import patterns, include, url # Uncomment ...
- 友盟消息push功能
友盟地址:https://i.umeng.com/user/products 一.android 1.产品->U-App/U-push->立即使用->管理->左侧-集成测试-& ...
- ID3D11DeviceContext::DrawIndexed DrawIndexed 参数详解 StartIndexLocation BaseVertexLocation
先来看一下画的结果: m_pImmediateContext->DrawIndexed(36, 0, 0); 这个是画一个立方体 后两个参数都是0没有什么可说的. m_pImmediateCon ...
- std::string begin end
std::string 的begin到end是不包含 ‘\0’的
- java struts2入门学习实例--用户注册和用户登录整合
需求: 1.用户注册(user_register.jsp)-->注册成功(UserRegister.action)-->显示注册信息(register_success.jsp)2.用户登录 ...