Java常见序列化与反序列方法总结
很多商业项目用到数据库、内存映射文件和普通文件来完成项目中的序列化处理的需求,但是这些方法很少会依靠于Java序列化。本文也不是用来解释序列化的,而是一起来看看面试中有关序列化的问题,这些问题你很有可能不了解。“Java序列化指的是将对象转换程字节格式并将对象状态保存在文件中,通常是.ser扩展名的文件。然后可以通过.ser文件重新创建Java对象,这个过程为返序列化”
Java序列化的API中提供了开发人员进行序列化对象的机制,通过Serializable和Externalizable接口。
一起看看这些问题:
1)Java中的Serializable接口和Externalizable接口有什么区别?
这个是面试中关于Java序列化问的最多的问题。我的回答是,Externalizable接口提供了两个方法writeExternal()和readExternal()。这两个方法给我们提供了灵活处理Java序列化的方法,通过实现这个接口中的两个方法进行对象序列化可以替代Java中默认的序列化方法。正确的实现Externalizable接口可以大幅度的提高应用程序的性能。
2)Serializable接口中有借个方法?如果没有方法的话,那么这么设计Serializable接口的目的是什么?
Serializable接口在java.lang包中,是Java序列化机制的核心组成部分。它里面没有包含任何方法,我们称这样的接口为标识接口。如果你的类实现了Serializable接口,这意味着你的类被打上了“可以进行序列化”的标签,并且也给了编译器指示,可以使用序列化机制对这个对象进行序列化处理。
3)什么是serialVersionUID?如果你没有定义serialVersionUID意味着什么?
SerialVersionUID应该是你的类中的一个public static final类型的常量,如果你的类中没有定义的话,那么编译器将抛出警告。如果你的类中没有制定serialVersionUID,那么Java编译器会根据类的成员变量和一定的算法生成用来表达对象的serialVersionUID ,通常是用来表示类的哈希值(hash code)。结论是,如果你的类没有实现SerialVersionUID,那么如果你的类中如果加入或者改变成员变量,那么已经序列化的对象将无法反序列化。这是以为,类的成员变量的改变意味这编译器生成的SerialVersionUID的值不同。Java序列化过程是通过正确SerialVersionUID来对已经序列化的对象进行状态恢复。
4)当对象进行序列化的时候,如果你不希望你的成员变量进行序列化,你怎么办?
这个问题也会这么问,如何使用暂态类型的成员变量?暂态和静态成员变量是否会被序列化等等。如果你不希望你的对象中的成员变量的状态得以保存,你可以根据需求选择transient或者static类型的变量,这样的变量不参与Java序列化处理的过程。
5)如果一个类中的成员变量是其它符合类型的Java类,而这个类没有实现Serializable接口,那么当对象序列化的时候会怎样?
如果你的一个对象进行序列化,而这个对象中包含另外一个引用类型的成员编程,而这个引用的类没有实现Serializable接口,那么当对象进行序列化的时候会抛出“NotSerializableException“的运行时异常。
6)如果一个类是可序列化的,而他的超类没有,那么当进行反序列化的时候,那些从超类继承的实例变量的值是什么?
Java中的序列化处理实例变量只会在所有实现了Serializable接口的继承支路上展开。所以当一个类进行反序列化处理的时候,超类没有实现Serializable接口,那么从超类继承的实例变量会通过为实现序列化接口的超类的构造函数进行初始化。
7) Can you Customize Serialization process or can you override default Serialization process in Java?
7)你能够自定义序列化处理的代码吗或者你能重载Java中默认的序列化方法吗?
答案是肯定的,可以。我们都知道可以通过ObjectOutputStream中的writeObject()方法写入序列化对象,通过ObjectInputStream中的readObject()读入反序列化的对象。这些都是Java虚拟机提供给你的两个方法。如果你在你的类中定义了这两个方法,那么JVM就会用你的方法代替原有默认的序列化机制的方法。你可以通过这样的方式类自定义序列化和反序列化的行为。需要注意的一点是,最好将这两个方法定义为private,以防止他们被继承、重写和重载。也只有JVM可以访问到你的类中所有的私有方法,你不用担心方法私有不会被调用到,Java序列化过程会正常工作。
8)假设一个新的类的超类实现了Serializable接口,那么如何让这个新的子类不被序列化?
如果一个超类已经序列化了,那么无法通过是否实现什么接口的方式再避免序列化的过程了,但是也还有一种方式可以使用。那就是需要你在你的类中重新实现writeObject()和readObject()方法,并在方法实现中通过抛出NotSerializableException。
9)在Java进行序列化和反序列化处理的时候,哪些方法被使用了?
这个是面试中常见的问题,主要用来考察你是否对readObject()、writeObject()、readExternal()和writeExternal()方法的使用熟悉。Java序列化是通过java.io.ObjectOutputStream这个类来完成的。这个类是一个过滤器流,这个类完成对底层字节流的包装来进行序列化处理。我们通过ObjectOutputStream.writeObject(obj)进行序列化,通过ObjectInputStream.readObject()进行反序列化。对writeObject()方法的调用会触发Java中的序列化机制。readObject()方法用来将已经持久化的字节数据反向创建Java对象,该方法返回Object类型,需要强制转换成你需要的正确类型。
10) Suppose you have a class which you serialized it and stored in persistence and later modified that class to add a new field. What will happen if you deserialize the object already serialized?
10)假设你有一个类并且已经将这个类的某一个对象序列化存储了,那么如果你在这个类中加入了新的成员变量,那么在反序列化刚才那个已经存在的对象的时候会怎么样?
这个取决于这个类是否有serialVersionUID成员。通过上面的,我们已经知道如果你的类没有提供serialVersionUID,那么编译器会自动生成,而这个serialVersionUID就是对象的hash code值。那么如果加入新的成员变量,重新生成的serialVersionUID将和之前的不同,那么在进行反序列化的时候就会产生java.io.InvalidClassException的异常。这就是为什么要建议为你的代码加入serialVersionUID的原因所在了。
11)JAVA反序列化时会将NULL值变成""字符!!
Java常见序列化与反序列方法总结的更多相关文章
- Java使用序列化的私有方法巧妙解决部分属性持久化问题
部分属性持久化问题看似很简单,只要把不需要的持久化的属性加上瞬态关键字(transient关键字)即可,没错,这也是一种解决方案,但在有的时候行不通,例如在一个计税系统和人力系统对接的时候,计税系统需 ...
- 一段网上java常见escape和unescape方法的BUG
escape编码和unescape编码,就是将一个字符转换为16进制unicode编码,前面加%字符进行标识. 此处不再多做解释,参考这里:http://www.jb51.net/article/23 ...
- Java 序列化 和 反序列--by Vincent
序列化: Java 提供了一种把对象序列化的机制. 即把一个对象可以被表示为一个字节序列.然后可以写入文件保存. 字节序列包括: 该对象的数据.有关对象的类型的信息和存储在对象中数据的类型. ...
- Java常见的几种内存溢出及解决方法
Java常见的几种内存溢出及解决方法[情况一]:java.lang.OutOfMemoryError:Javaheapspace:这种是java堆内存不够,一个原因是真不够(如递归的层数太多等),另一 ...
- Java 获取*.properties配置文件中的内容 ,常见的两种方法
import java.io.InputStream; import java.util.Enumeration; import java.util.List; import java.util.Pr ...
- Java对象序列化和反序列化的工具方法
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...
- JAVA常见中文问题的解决方法(转)
JAVA常见中文问题的解决方法 http://www.java-cn.com/club/article-5876-1.html 以下解决方案是笔者在日常生活中遇到的,希望能对你解决JAVA中文问题有所 ...
- Java常见对象Object类中的个别方法
Java常见对象Object类 public int hashCode() : 返回该对象的哈希码值. 注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值.你可以理解成 ...
- Java实现 LeetCode 449 序列化和反序列化二叉搜索树
449. 序列化和反序列化二叉搜索树 序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建. 设计一个算法 ...
随机推荐
- JVM启动参数手册——JVM之八
jdk1.4.2 JVM官方地址:http://java.sun.com/j2se/1.4.2/docs/guide/vm/index.html 标准和非标注参数(for windows):http: ...
- 十大面试问题解惑,秒杀一切HR、技术面试
最能体现求职者能力的就是面试,能不能拿到Offer,取决于你面试时的表现,只有有准备才能在面试过程中游刃有余.小编收集了10个面试官最爱提的问题,虽然题目千变万化,但是万变不离其宗,只要掌握了答题的技 ...
- 从Hello, world开始认识IL <第一篇>
IL代码分析方法 Hello, world历史 .NET学习方法论 1.引言 1988年Brian W.Kernighan和Dennis M.Ritchie合著了软件史上的经典巨著<The C ...
- jQuery的入门与简介《思维导图》
<初学者请各位高手指点指点> jQuery是继Prototype之后又一个优秀的JavaScript库,在JavaScript基础上我知道了jQuery拥有强大的选择器, 出色的DOM操作 ...
- Eclipse IDE for Java EE Developers使用和新建工程helloworld
开发j2ee还是用专门的java ee eclipse,自带了许多开发j2ee的插件,包括: This package includes: Data Tools Platform Eclipse Gi ...
- 导入时如何定制spring-boot依赖项的版本
spring-boot通过maven的依赖管理为我们写好了很多依赖项及其版本,我们可拿来使用.spring-boot文档介绍了两种使用方法,一是继承,二是导入. 通过<parent>继承: ...
- Unity position和localposition
1. position是根据世界原点为中心 2. localPosition是根据父节点为中心,如果没有父节点,localpositon和position是没有区别的 3.选中一个物体左上角Globa ...
- [每日一题] OCP1z0-047 :2013-08-18 禁用启用约束――主键与外键 ..................................61
正确答案:C 根据题意,测试结果如下: 1.创建表emp,并且设emp_no字段为主键,设mgr_no字段为外键. gyj@MYDB> create table emp 2 (emp_no nu ...
- hdu 3061 (最大权闭合图)
分析:城池之间有依赖关系,汇点与能获得兵力的城池连接,容量为可以获得的兵力,损耗兵力的城池与汇点连接容量为损耗的兵力,有依赖关系的城池间连边,容量为无穷大,跑网络流求出的最小割就是损耗的最小兵力,,, ...
- Base64编码和解码算法
Base64么新鲜的算法了.只是假设你没从事过页面开发(或者说动态页面开发.尤其是邮箱服务),你都不怎么了解过,仅仅是听起来非常熟悉. 对于黑客来说,Base64与MD5算法有着相同的位置.由于电子邮 ...