Java Serializable接口(序列化)理解及自定义序列化
1 Serializable接口
(1)简单地说,就是可以将一个对象(标志对象的类型)及其状态转换为字节码,保存起来(可以保存在数据库,内存,文件等),然后可以在适当的时候再将其状态恢复(也就是反序列化)。serialization 不但可以在本机做,而且可以经由网络操作。它自动屏蔽了操作系统的差异,字节顺序等。比如,在 Windows 平台生成一个对象并序列化之,然后通过网络传到一台 Unix 机器上,然后可以在这台Unix机器上正确地重构(deserialization)这个对象。 不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。
另外,还应明白以下几点:
a. java.io.Serializable接口没有任何方法属性域,实现它的类只是从语义上表明自己是可以序列化的。
b. 在对一个 Serializable(可序列化)对象进行重新装配的过程中,不会调用任何构建器(甚至默认构建器)。整个对象都是通过从 InputStream 中取得数据恢复的。
c. 如是要一个类是可序列化的,那么它的子类也是可序列化的。
(2)serialVersionUID
serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。
类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。为了提高哦啊serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。显式地定义serialVersionUID有两种用途:
a. 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
b. 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
2 自定义序列化:
自定义序列化是由ObjectInput/OutputStream在序列化/反序列化时候通过反射检查该类是否存在以下方法(0个或多个):执行顺序从上往下,序列化调用1和2,反序列调用3和4;transient关键字当某个字段被声明为transient后,默认序列化机制就会忽略该字段。
1Object writeReplace() throws ObjectStreamException;可以通过此方法修改序列化的对象
2void writeObject(java.io.ObjectOutputStream out) throws IOException; 方法中调用defaultWriteObject() 使用writeObject的默认的序列化方式,除此之外可以加上一些其他的操作,如添加额外的序列化对象到输出:out.writeObject("XX")
3void readObject(java.io.ObjectInputStream in) throws Exception; 方法中调用defaultReadObject()使用readObject默认的反序列化方式,除此之外可以加上一些其他的操作,如读入额外的序列化对象到输入:in.readObject()
4Object readResolve() throws ObjectStreamException;可以通过此方法修改返回的对象
例子:单例模式的类实现序列化接口,若使用默认的序列化策略,则在反序列化返回的对象不符合单利模式(反射创建了新的对象,如下PersonSington对象),可以通过修改序列化的readResolve来实现自定义序列化返回结果来实现单例对象唯一(相当于1,2,3方法对4的结果毫无作用)。
public class PersonSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private PersonSingleton(String name) {
this.name = name;
};
private static PersonSingleton person = null;
public static synchronized PersonSingleton getInstance() {
if (person == null)
return person = new PersonSingleton("cgl");
return person;
}
private Object writeReplace() throws ObjectStreamException {
System.out.println("1 write replace start");
return this;//可修改为其他对象
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
System.out.println("2 write object start");
out.defaultWriteObject();
//out.writeInt(1);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("3 read object start");
in.defaultReadObject();
//int i=in.readInt();
}
private Object readResolve() throws ObjectStreamException {
System.out.println("4 read resolve start");
return PersonSingleton.getInstance();//不管序列化的操作是什么,返回的都是本地的单例对象
}
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream(new File("D://person.dat"));
ObjectOutputStream op = new ObjectOutputStream(out);
op.writeObject(PersonSingleton.getInstance());
op.close();
FileInputStream in = new FileInputStream(new File("D://person.dat"));
ObjectInputStream oi = new ObjectInputStream(in);
Object person = oi.readObject();
in = new FileInputStream(new File("D://person.dat"));
oi = new ObjectInputStream(in);
PersonSinglton person1 = (PersonSinglton) oi.readObject();
System.out.println("sington person hashcode:" + person.hashCode());
System.out.println("sington person1 hashcode:" + person1.hashCode());
System.out.println("singleton getInstance hashcode:" + PersonSingleton.getInstance().hashCode());
System.out.println("singleton person equals:" + (person == PersonSingleton.getInstance()));
System.out.println("person equals1:" + (person1 == person));
}
}
运行结果:
1 write replace start
2 write object start
3 read object start
4 read resolve start
3 read object start
4 read resolve start
sington person hashcode:1550089733
sington person1 hashcode:1550089733
sington getInstance hashcode:1550089733
sington person equals:true
person equals1:true
3 Externalizable接口
Externalizable继承于Serializable,当使用该接口时,序列化的细节需要由程序员去完成。若writeExternal()与readExternal()方法未作任何处理,那么该序列化行为将不会保存/读取任何一个字段。出结果中所有字段的值均为空。
另外,若使用Externalizable进行序列化,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。由于这个原因,实现Externalizable接口的类必须要提供一个无参的构造器,且它的访问权限为public。
Java Serializable接口(序列化)理解及自定义序列化的更多相关文章
- WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化
WPF中的常用布局 一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...
- JAVA回调接口的理解
A类持有B接口的对象引用,B接口有一个callBack()方法,C类是B类的实现类,实现了callBack()方法,把C类传入A类,当A类执行完操作后调用callBack()方法,这时候A调用的就是C ...
- 对Java Serializable(序列化)的理解和总结
我对Java Serializable(序列化)的理解和总结 博客分类: Java技术 JavaOSSocketCC++ 1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状 ...
- 对Java Serializable(序列化)的理解和总结(一)
导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...
- Java Serializable(序列化)的理解和总结
1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object st ...
- 谈谈序列化—实体bean一定要实现Serializable接口?
导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...
- java自定义序列化
自定义序列化 1.问题引出 在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Ser ...
- Java 自定义序列化、反序列化
1.如果某个成员变量是敏感信息,不希望序列化到文件/网络节点中,比如说银行密码,或者该成员变量所属的类是不可序列化的, 可以用 transient 关键字修饰此成员变量,序列化时会忽略此成员变量. c ...
- Java——对象的复制、克隆、序列化
原创作者: https://blog.csdn.net/lmb55/article/details/78277878对象克隆(复制)假如说你想复制一个简单变量.很简单: int apples = 5; ...
随机推荐
- netty源码分析
1.Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.也就是说,Netty 是一个基于N ...
- Mac关机时处于黑屏状态
PS:不知道大家有没有遇到过mac电脑关机就黑屏,只有一个箭头,还可以滑动箭头,但就是黑屏状态,等个好长时间还是关不了机,因此我查了好多资料,原因是在关机时,mac要先关掉其他软件或者保存进程以备下次 ...
- 关于网页授权的两种scope的区别说明
关于网页授权的两种scope的区别说明 1.以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的.用户感知的就是直接进入了回 ...
- 简介CentOS与 Ubuntu的不同
1.关于登录用户 centos可以使用root登录 ubuntu不能使用root登录 centos普通用户默认不能通过sudo取得root权限执行命令, ubuntu可以,centos需要sudo时 ...
- em标签和strong标签的区别
今天模拟面试,第一个问题就是这个,然后我回答说就是表示强调,然后老师说还有吗,我说不知道了,然后,就没有然后了... 第一个层次的区别: <em>标签是告诉浏览器把其中的文本表示为强调的内 ...
- Linux下实现视频读取(三)---Buffer的准备和数据读取
前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度.曝光时间,帧数,增益.白平衡等.今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取. 1. 初始化 Memory ...
- IDE转AHCI
1.Win + R.输入regedit.进入注冊表编辑器 2.找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Msahci.将当中的&qu ...
- freemarker四种变量
freemarker四种变量 1.简单介绍说明 (1)数据模型中的变量:root中的变量 (2)模板中的变量:使用<#assign>定义的变量 (3)局部变量:在指令中的变量 (4)循环变 ...
- Android binder学习一:主要概念
要看得懂android代码,首先要了解binder机制.binder机制也是android里面比較难以理解的一块,这里记录一下binder的重要概念以及实现.作为备忘. 部分内容来源于网上,如有侵权. ...
- ASP.NET WebAPI使用Swagger生成测试文档
ASP.NET WebAPI使用Swagger生成测试文档 SwaggerUI是一个简单的Restful API测试和文档工具.简单.漂亮.易用(官方demo).通过读取JSON配置显示API .项目 ...