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. 序列化和反序列化二叉搜索树 序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建. 设计一个算法 ...
随机推荐
- Delphi之通过代码示例学习XML解析、StringReplace的用法(异常控制 good)
*Delphi之通过代码示例学习XML解析.StringReplace的用法 这个程序可以用于解析任何合法的XML字符串. 首先是看一下程序的运行效果: 以解析这样一个XML的字符串为例: <? ...
- 【Xamarin挖墙脚系列:关闭 OS X El Capitan 中 SIP 安全设置功能】
比如需要修改内核配置文件: com.apple.Boot.plist 那么我们需要解锁权限. 禁止SIP模式,那么就可以修改此文件了. 在 OS X El Capitan 中有一个跟安全相关的模式叫 ...
- C语言调用库函数实现生产者消费者问题
#include<stdio.h> #include<stdlib.h> #include<semaphore.h> #include<pthread.h&g ...
- 借贷宝注册送现金疯转 新闻PS图背后真相
动动手指,20元人民币立即到手:http://www.cnblogs.com/mfryf/p/4754384.html 近日,九鼎投资旗下投资平台借贷宝开展的“拉上好友抢红包,轻轻松松玩出钱”引起市场 ...
- OpenStack 部署总结之:在CentOS 6.5上使用RDO单机安装icehouse(Ml2+GRE)
本文主要介绍怎样在CentOS6.5上通过RDO来安装icehouse,因为安装的过程中涉及的软件较多,以及依赖关系比較复杂,建议使用一个全新的操作系统来进行安装. 安装步骤详细例如以下 (1)安装操 ...
- apache 开启压缩功能
apache如何开启压缩功能. 1,首先先确认是安装deflatte模块.如果未安装,可以重新编译apache添加参数--enable-deflate=shared ,或者扩展安装deflate模块, ...
- angular $location常用方法使用
$location提供了一些常用的操作和获取地址栏里的地址的方法. <script type="text/javascript"> angular.module('ap ...
- asp.net 常用的3中身份验证
1. windows验证: IIS根据应用程序的设置来进行身份验证,要使用这中验证方式,必须禁止使用匿名用户登录. 2. Forms验证: 通过Cookies来保存用户凭证,对未登录的用户 重定向到自 ...
- appium安装 For windows
java sdk,android SDK,maven,genymotion全部已经安装完毕,只是安装appium 因为现在的appium(AppiumForWindows_1_4_13_1)需要自己重 ...
- Intent中的重要属性详解
Intent中的四个重要属性主要有四个,分别是Action.Data.Category.Extras. Intent作为联系各Activity,BroadcaseReciver,Service之间的纽 ...