序列化这个概念在所有的项目开发中都有。
1. 序列化概念
对象序列化指的是:将内存中保存的对象变为二进制数据流的形式进行传输,或者是将这个二进制数据流保存在文本中。
但这并不意味着所有类的对象都需要被序列化,严格来讲,需要被序列化的类对象往往需要传输使用,同时这个类必须实现java.io.Serializable接口。
Serializable接口是一个标识接口,里面没有任何方法,继承它的类意味着要被序列化。
public interface Serializable {
}
序列化对象时所需要保存的就是对象中的属性,所以默认情况下对象的属性将被转为二进制数据流存在。
2. 序列化与反序列化操作
这里我们将序列化的数据保存在文件中以方便演示。
序列化本质就是将继承了Serializable接口的类的属性信息转化为二进制信息,而反序列化与之相反,把序列化的二进制信息转化为类的信息。
如果要想实现序列化与反序列化的对象操作,在java.io包中提供有两个处理类:ObjectOutputStream,ObjectInputStream,如下所示:
public class ObjectOutputStream
extends OutputStream implements ObjectOutput, ObjectStreamConstants
public class ObjectInputStream
extends InputStream implements ObjectInput, ObjectStreamConstants
它们的继承结构如下:
- ObjectOutputStream
- ObjectInputStream
序列化和反序列化操作:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 测试路径:E:\IO\demo.txt
*/
@SuppressWarnings("serial")
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "[name: "+this.name+", age: "+this.age+"]";
}
}
public class Test {
public static final File file = new File("E:\\IO\\demo.txt");
public static void main(String[] args) throws Exception {
Person person = new Person("xucc", 10);
// 序列化
serialization(person);
// 反序列化,并在控制台中打印信息
deserialization(person);
}
// 序列化
public static void serialization(Object obj) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(obj);
// 关闭流
oos.close();
}
// 反序列化
public static void deserialization(Object obj) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
System.out.println(ois.readObject());
ois.close();
}
}
运行程序前测试文件夹:
运行后转化的二进制序列化信息:
控制台打印出的反序列化信息:
3. transient关键字
在序列化时,实现了Serializable接口的类,JVM会默认将对象中所有属性进行序列化保存,如果现在某些属性不希望被保存了,那么就可以使用transient关键字屏蔽该属性的序列化。
以上面程序为例,修改其中的Person类
class Person implements Serializable {
private String name;
// 使用 transient关键字 修饰该属性,该属性将不被序列化
private transient int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "[name: "+this.name+", age: "+this.age+"]";
}
}
运行程序后控制台信息为:
因为 age 被 transient 修饰了,所以该属性的值显示为 int 类型的默认值 0。
但是在实际工程中,大部分情况下使用序列化往往是在简单java类上,其他类上使用序列化的操作模式相对较少。
而如果是简单java类,也就很少去使用transient关键字了,了解即可。