文章目录
几乎只要是 Java 开发就一定会存在有序列化的概念,而正是因为序列化的概念逐步发展,慢慢地也有了更多 的序列化标准
什么是序列化?
所谓的对象序列化指的是将内存中保存的对象以二进制数据流的形式进行处理,可以实现对象的保存或者是网络传输
然而并不是所有的对象都可以被序列化的,在 Java 里面有一个强制性的要求:如果要序列化的对象,那么对象所在的类一定要实现 java.io.Serializable 父接口,作为序列化的标记,这个接口并没有任何的方法,为什么?因为它描述的是一种类的能力
举例:(定义一个可以被序列化的类)
class Person implements Serializable { // Person 类可以被序列化
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 省略 setter getter
@Override
public String toString() {
return "姓名:" + this.name + "、年龄:" + this.age;
}
}
此时 Person 类产生的每一个对象都可以实现二进制的数据传输,属于可以被序列化的程序类
序列化与反序列化
有了序列化的支持类之后如果想要实现序列化与反序列化的操作则就可以利用以下两个类完成:
类名称 | 序列化:ObjecOutputStream | 反序列化:ObjectInputStream |
---|---|---|
类定义 | public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants | public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants |
构造方法 | public ObjectOutputStream(OutputStream out) throws IOException | public ObjectInputStream(InputStream in) throws IOException |
操作方法 | public final void writeObject(Object obj) throws IOException | public final Object readObject() throws IOException, ClassNotFoundException |
举例:(实现序列化与反序列化)
package com.java.springtest.testdemo;
import java.io.*;
/**
* @author Woo_home
* @create by 2020/1/31
*/
class Person implements Serializable { // Person 类可以被序列化
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 省略 setter getter
@Override
public String toString() {
return "姓名:" + this.name + " 年龄:" + this.age;
}
}
public class Demo {
private static final File SAVE_FILE = new File("D:" + File.separator + "demo.person");
public static void saveObject(Object object) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oos.writeObject(object); // 序列化
oos.close();
}
public static Object loadObject() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj = ois.readObject(); // 反序列化
ois.close();
return obj;
}
public static void main(String[] args) throws Exception {
saveObject(new Person("lisa",10));// 序列化
System.out.println(loadObject()); // 反序列化
}
}
运行该程序之后会在 D 盘生成一个 demo.person 的文件
我们打开这个文件发现它存储的是一个二进制
控制台输出:
在 Java 中的对象序列化与反序列化必须使用内部提供的对象操作流,因为这里面牵扯到二进制数据的格式,所以不能自定义处理,另外如果想要实现一组对象的序列化,则可以使用对象数组完成
在很多的实际项目开发过程之中,开发者很少能够见到 ObjectOutputStream、ObjectInputStream 类的直接操作,因为会有一些容器帮助开发者自动实现
transient 关键字
默认情况下当执行了对象序列化的时候会将类中的全部属性的内容进行全部的序列化操作,但是很多情况下有一些属性可能并不需要进行序列化的处理,这个时候就可以在属性定义上使用 transient 关键字来完成了
private transient String name;
如果在属性加上了 transient 关键字之后,那么在进行序列化处理的时候 name 属性的内容是不会被保存下来的,换言之,读取的数据 name 将是其对应数据类型的默认值(null)
举例:(transient 关键字的使用)
我们把上门的程序中的 name 属性加上 transient 关键字之后再执行一次,可以看到 name 输出为 null 了
什么时候会使用到 transient 关键字?
如果假设类之中有一些是需要计算保存的属性内容往往是不需要被序列化的,这个时候就可以使用 transient 关键字了,但是呢在实际上的开发之中大部分需要被序列化的类往往都是简单的 Java 类(比如 Java web 开发中的实体类),所以这一个关键字的出现频率并不高,但是得知道有这么一个关键字叫 transient