对象序列化的目标是将对象保存在磁盘中,或者允许在网络中直接传输对象。

对象序列化允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久保存在磁盘上或者通过网络将这种二进制流传输到另外一个网络节点。

其他程序一旦获得了这种二进制流,都可以将这种二进制流恢复成原本的Java对象。

序列化的含义和意义

序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以进行持久化或者通过网络传输,使得对象可以脱离程序的运行而独立存在。

序列化将一个Java对象写入IO流中。对象的反序列化可以从IO流中恢复该Java对象。

如果想要让某个对象支持序列化机制,那么必须让它的类是可以序列化的。为了让某个类是可序列化的,那么该类必须实现如下两个接口之一:

  • Serializable
  • Externalizable

使用对象流实现序列化

使用Serializable来实现序列化非常简单,主要让目标类实现该标记接口即可,无需实现任何方法。一旦某个类实现了Serializable接口,该类的对象就是可序列化的。

考虑下面这个例子:

首先展示用来序列化的Person类:

public class Person implements java.io.Serializable{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void talk(){
System.out.println("我是"+name+"我已经"+age+"岁了!");
}
}

接下里的代码展现了如何序列化和反序列化:

import java.io.*;

public class Serializable {
public static void main(String[] args){
try(
//创建一个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:/test.txt"))
)
{
Person per = new Person("AmosH",20);
//将per对象写入输出流
oos.writeObject(per);
}catch (IOException ex){
ex.printStackTrace();
} try(
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:/test.txt"))
)
{
//反序列化per对象,如果知道对象的类型,可以直接采用强制类型转换成实际类型
Person per = (Person)ois.readObject();
//输出我是AmosH我已经20岁了!
per.talk();
}catch (Exception ex){
ex.printStackTrace();
}
}
}

需要注意的四点是:

  1. 反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化回复Java对象时,必须提供该Java对象所属类的class文件,否则将会引起ClassNotFoundException异常。
  2. 当反序列化读取Java对象时,无需通过构造器来初始化对象。
  3. 如果使用序列化机制在文件中写入了多个Java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。
  4. 当一个可序列化类有多个父类(包括直接父类和间接父类),这些父类要么包含无参数的构造器,要么也是可序列化的。否则反序列化时将会抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类中定义的成员变量值不会序列化到二进制流中。

对象引用的序列化

当被序列化的对象中包含的成员变量的类型不是基本类型而是一个引用类型时,那么这个引用类必须是可序列化的,否则拥有该类型成员变量的类也是不可序列化的。

我们假设如下一种情况:

程序中有一个Student对象和两个Teacher对象,两个Teacher对象中都有成员变量引用这个Student对象。

在这样的情形下,如果我们序列化这三个对象,因为程序在序列化Teacher对象时也会将其中的引用对象实例序列化,那么似乎程序会向输出流中输出三个Person对象。

如果程序想输出流中输出了三个Person对象,那么程序从输入流中反序列化这些对象时,将会得到三个Student对象,两个Teacher对象所引用的Student对象将不是同一个对象,这显然也违背了Java序列化机制的初衷。

所以,Java序列化机制采用了一种特殊的序列化算法:

  • 所有保存到磁盘中的对象都有一个序列化编号。
  • 当程序试图序列化一个对象时,程序先会检查该对象是否已经被序列化过。只有该对象并为在本次虚拟机中被序列化过,系统才会将该对象转换成字节序列并输出。
  • 如果某个对象已经序列化过,则程序将只是直接输出一个序列化编号而不是再次重新序列化该对象。

但是要注意的是:如果序列化的是一个可变对象时,只有第一次序列化才会将对象转换成字节序列并输出。当对象的实例变量值已经改变之后,及时再次序列化,也只会输出前面的序列化编号。

在Java中进行序列化和反序列化的更多相关文章

  1. java中的序列化与反序列化,还包括将多个对象序列化到一个文件中

    package Serialize; /** * Created by hu on 2015/11/7. */ //实现序列化必须实现的接口,这就是一个空接口,起到标识的作用 import java. ...

  2. K:java中的序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?以下内容将围绕这些问题进行展开讨论. Java序列化与反序列化 简单来说Java序列化是指把Java对象转 ...

  3. Java中的序列化与反序列化

    序列化定义 将对象转换为字节流保存起来,并在以后还原这个对象,这种机制叫做对象序列化. 将一个对象保存到永久存储设备上称为持久化. 一个对象要想能够实现序列化,必须实现java.io.Serializ ...

  4. java中的序列化和反序列化学习笔记

    须要序列化的Person类: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableException:未序列化 ...

  5. java中的序列化和反序列化

    package cn.zhou; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.Fil ...

  6. 【Java基础】序列化与反序列化深入分析

    一.前言 复习Java基础知识点的序列化与反序列化过程,整理了如下学习笔记. 二.为什么需要序列化与反序列化 程序运行时,只要需要,对象可以一直存在,并且我们可以随时访问对象的一些状态信息,如果程序终 ...

  7. Java对象的序列化与反序列化

    序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是 ...

  8. Java对象的序列化和反序列化[转]

    Java基础学习总结--Java对象的序列化和反序列化 一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化.把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用 ...

  9. JAVA基础之——序列化和反序列化

    1 概念 序列化,将java对象转换成字节序列的过程. 反序列化,将字节序列恢复成java对象的过程. 2 为什么要序列化? 2.1 实现数据持久化,当对象创建后,它就会一直在,但是在程序终止时,这个 ...

随机推荐

  1. job定时任务

    1,定时任务依赖的执行类 2.引入job 3.执行时间 4.管理job

  2. Using iSCSI On Ubuntu 10.04 (Initiator And Target)

    This guide explains how you can set up an iSCSI target and an iSCSI initiator (client), both running ...

  3. 2.AsyncQueryHandler、内容提供者

    会话页面 Test :测试 public class Test extends AndroidTestCase{ public void test(){ Uri uri = Uri.parse(&qu ...

  4. genymotion常见问题解答

    [转]常见问题解答 很多人喜欢使用Genymotion这款安卓模拟器,但是虽然Genymotion很好用,可是却有各种问题存在哦,下面潇潇就一些常见的Genymotion问题来说下解决方法吧. 为什么 ...

  5. Eclipse 中 Maven 项目 pom.xml 提示错误 org.codehaus.plexus.archiver.jar.Manifest.write(java.io.PrintWriter)

    从SVN上下载到Eclipse工作空间的项目一直报如下错误,进行一下Maven ---> Update Project... 就不报错了,但是过一会又会报错 查找资料初步确定是Eclipse中自 ...

  6. 第33节:Java面向对象中的异常

    Java中的异常和错误 Java中的异常机制,更好地提升程序的健壮性 throwable为顶级,Error和Exception Error:虚拟机错误,内存溢出,线程死锁 Exception:Runt ...

  7. 大数据基础Hadoop 2.x入门

    hadoop概述 存储和分析网络数据 三大组件 MapReduce 对海量数据的处理 思想: 分而治之 每个数据集进行逻辑业务处理map 合并统计数据结果reduce HDFS 储存海量数据 分布式存 ...

  8. rabbitmq系统学习(二)

    Rabbitmq高级整合应用 RabbitMq整合Spring AMQP实战 RabbitAdmin 使用RabbitTemplate的execute方法执行对应操作 rabbitAdmin.decl ...

  9. Ubuntu18.04下配置Nginx+RTMP服务器,实现点播/直播/录制功能

    2019.3.22更新 最新的nginx-1.15.9可与openssl1.1.1兼容了 以下原文: 这个东西我眼馋挺久了,最近终于试玩了一下,感觉很好玩,在搭建的过程在也遇到一些坑,这里总结一下 安 ...

  10. Ocelot简易教程(四)之请求聚合以及服务发现

    上篇文章给大家讲解了Ocelot的一些特性并对路由进行了详细的介绍,今天呢就大家一起来学习下Ocelot的请求聚合以及服务发现功能.希望能对大家有所帮助. 作者:依乐祝 原文地址:https://ww ...