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接口(序列化)理解及自定义序列化的更多相关文章

  1. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  2. JAVA回调接口的理解

    A类持有B接口的对象引用,B接口有一个callBack()方法,C类是B类的实现类,实现了callBack()方法,把C类传入A类,当A类执行完操作后调用callBack()方法,这时候A调用的就是C ...

  3. 对Java Serializable(序列化)的理解和总结

    我对Java Serializable(序列化)的理解和总结 博客分类: Java技术 JavaOSSocketCC++  1.序列化是干什么的?       简单说就是为了保存在内存中的各种对象的状 ...

  4. 对Java Serializable(序列化)的理解和总结(一)

    导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...

  5. Java Serializable(序列化)的理解和总结

    1.序列化是干什么的?       简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object st ...

  6. 谈谈序列化—实体bean一定要实现Serializable接口?

    导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...

  7. java自定义序列化

    自定义序列化 1.问题引出 在某些情况下,我们可能不想对于一个对象的所有field进行序列化,例如我们银行信息中的设计账户信息的field,我们不需要进行序列化,或者有些field本省就没有实现Ser ...

  8. Java 自定义序列化、反序列化

    1.如果某个成员变量是敏感信息,不希望序列化到文件/网络节点中,比如说银行密码,或者该成员变量所属的类是不可序列化的, 可以用 transient 关键字修饰此成员变量,序列化时会忽略此成员变量. c ...

  9. Java——对象的复制、克隆、序列化

    原创作者: https://blog.csdn.net/lmb55/article/details/78277878对象克隆(复制)假如说你想复制一个简单变量.很简单: int apples = 5; ...

随机推荐

  1. 基于 HTML5 Canvas 的 3D 碰撞检测

    这是公司大神写的一个放官网上给用户学习的例子,我一开始真的不知道这是在干嘛,就只是将三个形状图元组合在一起,然后可以同时旋转.放大缩小这个三个图形,点击"Animate"就能让中间 ...

  2. Code Kata:螺旋矩阵 javascript实现

    1 2 3 4  5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9  如图所示,就是一个5*5的螺旋矩阵 我的思路如下: 第一步:拆分 ...

  3. 命令行保存指定目录文件的名字(可包含文件夹文字)到txt文本文件

    Microsoft Visual Studio中配置OpenCV解决方案属性的时候, 需要将OpenCV的lib扩展名的库文件添加到属性的依赖列表里面,网上的有些人博客里面直接给出的会有问题(但大多数 ...

  4. Spring Boot系列(一) Spring Boot介绍和基础POM文件

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...

  5. Emoji表情符号录入MySQL数据库报错的解决方式

    前言:手机app应用评论的时候,恢复表情符号.提示失败.​1,查看tomcat后台日志,核心报错信息例如以下:  Caused by: java.sql.SQLException: Incorrect ...

  6. F02 金融学第二定律 资金的积聚

    美国南北战争,北方取胜的关键在于发行了债券,从而积聚了资金,提升了北方军队战斗力. 纽约的逆袭,得益于伊利运河的修建,而伊利运河的建造需要的资金,全靠债券发行积聚的资金. 聚积起来的资金,往往决定了重 ...

  7. ABP入门系列(12)——如何升级Abp并调试源码

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 升级Abp 本系列教程是基于Abp V1.0版本,现在Abp版本已经升级至V1.4.2(截至 ...

  8. Spring Boot实战之逐行释义HelloWorld

    一.前言  研究Spring boot也有一小段时间了,最近会将研究东西整理一下给大家分享,大概会有10~20篇左右的博客,整个系列会以一个简单的博客系统作为基础,因为光讲理论很多东西不是特别容易理解 ...

  9. plsql本机不安装数据库连接远程数据库

    用PL/SQL连接oracle数据库,不管是本地的还是远程的,一般都需要安装oracle客户端   如何达到不安装oracle客户端,又能使用PL/SQL工具?     1. oracle官网提供了i ...

  10. MFC中应用对象的成员:窗口指针m_pMainWnd说明

    CVC_MFC_firstDlg dlg; //定义对话框对象m_pMainWnd = &dlg;  //这个定义的对话框 dlg 成为主窗口 应用程序对象成员变量m_pMainWnd是一个窗 ...