概述
序列化是指将对象的状态信息转换为可以存储或传输形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后可以通过从存储区中读取或者反序列化对象的状态,重新创建该对象.
- 序列化:利用ObjectOutputStream,把对象的信息,按照固定的格式转成一串字节值输出并持久保存到磁盘
- 反序列化:利用ObjectInputStream,读取磁盘中之前序列化好的数据,重新恢复成对象
特点/应用场景
- 需要序列化的文件必须实现Serializable接口,用来启用序列化功能
- 不需要序列化的数据可以修饰成static,原因:static资源属于类资源
- 不随着对象被序列化输出 每一个被序列化的文件都有一个唯一的id,如果没有添加此id,编译器会自动根据类的定义信息计算产生一个
- 在反序列化时,如果和序列化的版本号不一致,无法完成反序列化
- 常用与服务器之间的数据传输,序列化成文件,反序列化读取数据
- 常用使用套接字流在主机之间传递对象
- 不需要序列化的数据也可以被修饰成transient(临时的),只在程序运行期间在内存中存在,不会被序列化持久保存
涉及到的流对象
序列化:ObjectOutputStream ObjectOutputStream 将 Java 对象的基本数据类型写入 OutputStream,通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
构造方法: ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream 普通方法: writeObject(Object obj) 将指定的对象写入 ObjectOutputStream
反序列化:ObjectInputStream ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化重构对象。
构造方法: ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream 普通方法: readObject() 从 ObjectInputStream 读取对象
序列化 ObjectOutputStream
将内存上所产生的对象保存到一个文本文件中
所有要序列化的类都必须实现Serializable接口
Student implements Serializable{
private static final long serialVersionUID = 1L;
}
反序列化 ObjectInputStream
将本地文件中的内容(对象)–读取到内存上
基本格式:
序列化
准备一个对象
Student stu = new Student(1, "沪青棒");
File file = new File("D:\\stu.bak");
FileOutputStream fos = new FileOutputStream(file);
通过序列化流进行写入ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(fos);
通过序列化流写入一个对象
oos.writeObject(stu);
关闭
oos.close();
fos.close();
【序列化:Serializable】
有一个具体的类对象,它用于保存程序运行过程中,产生的数据。 目前它是在内存上的,程序一旦结束就没有了。 有么有可能,它运行过程中的类,包括里面的数据,保存下来。 下一次运行程序的时候,拿出来,继续操作。
把这个运行过程中的类及数据,保存成一个文件。
要使用的时候再读取出来。
【对象序列化】:
将一个有数据的类信息,写成一个文档,保存到硬盘上。
序列化的条件:
如果一个类对象,需要被序列化操作的,它不能是普通的类, 它必须是:Serializable 的实现类
import java.IO.Serializable;
public class 类 implements Serializable{}
【反序列化】:
把那个硬盘上的文件,读取到程序中,回到内存上变成类对象。
程序必须有原始的类对象文件:
序列后的生成的文件,它主要是运行过程中的数据。
反序列化的时候,把文件中的数据读取出来,通过 serialVersionUID去对应类
然后:实例化类,填入数据,恢复到内存上。
其中:
transient:修饰符: 正常使用,但是禁止序列化(序列化会忽略) 都是给属性使用的。
对象流:建立在基础的字节流之上【用于序列化】 ObjectInputStream ObjectOutputStream
序列化的实例:
1、首先创建一个需要被实例化的类,然后implements Serializable类
package com.xzm.test;
//导入序列化操作的接口包文件
import java.io.Serializable;
//自定义:用于的数据实体模型类
//没有行为,只有属性,用于存取数据
//需要 序列化的,
public class User implements Serializable {
//serialVersionUID:这个属性是固定的
//用户可以自定义它的值,long类型
//如果不写,程序会默认自动创建
//这个属性是提供程序把文件读取出来以后,转换成指定的类的一个对应成
//主要就是用于判断,转换的是不是同一个类
//【通常不用自定义,程序自动填充】---> 提示中选择第二项,分配
private static final long serialVersionUID = 3050851876068541840L;
//普通的属性及封装属性【会序列化】
private int id; //变量
private String name; //类对象
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//可以定义构造函数的,因为是特殊方法,不是行为
public User(int id, String name) {
this.id = id;
this.name = name;
}
//--------------------------------------------
// transient:修饰符
// 用于序列化,表示 暂时的
// 正常操作没有问题,内存上与普通的一样,
// 但是,它不会被序列化到物理文件中
public transient int age = 28;
}
2、将上面的User类实例化操作
package com.xzm.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class 序列化User {
public static void main(String[] args) {
//强制异常处理
try {
//第一步:
// 定义File对象,定义目标源。
// 内存数据写成文件,通常是不允许直接打开预览的
// 大部分应用程序是写后缀,
// 游戏类的会自定义名称,
// 标准开发的时候,推荐: .es
File f = new File("C:/aaa/User.es");
//第二步:创建 基础 字节 输出流
FileOutputStream fos = new FileOutputStream(f);
//第三步:
// 创建高层 对象 输出 流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//操作对象--->在内存
User u = new User(555, "张三");
//第四步:写文件,生成序列化文档
oos.writeObject(u);
//关闭
oos.close();
fos.close();
//提示:
System.out.println("保存成功!");
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
此时通过上面两步,已经将User类实例化了,现在再将它反序列化
package com.xzm.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class 反序列化es {
public static void main(String[] args) {
try {
//【反序列化】:把物理文件,恢复到内存
//第一步:(目标源)
File f = new File("C:/aaa/User.es");
//第二步:基础 字节 输入流
FileInputStream fis = new FileInputStream(f);
//第三步:高层对象输入流
ObjectInputStream ois = new ObjectInputStream(fis);
//第四步:
// 调用方法,读取文件,得到一个Object对象
// 文件读取到系统中,都是一个Object
Object obj = ois.readObject();
//第五步:
//转换类型,把对象转换成所对应的类
//这时,会判断: serialVersionUID 是否一样
User u = (User)obj;
//关闭
ois.close();
fis.close();
//============================================
System.out.println(u.getId());
System.out.println(u.getName());
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
文章到这差不多结束了,有关Android中的APT知识。可以查看《Android核心技术》这本电子文档。里面记录的很详细,还有Android中更多的核心技术笔记资料。需要进阶自己技术的朋友可以参考学习,点击查看免费方法。
总结
序列化与反序列化的操作,一帮用于单机程序的配置保存,特别是哪些单机的应用程序,游戏,都是这个操作。
- 应用程序:配置文件
- 游戏: 配置文件,存档