序列化说的是对象,静态字段不属于对象,所以无法序列化
1、为什么需要序列化
对于一个复杂的对象,因为对象中到处引用,导致这个对象在堆内存中到处都是,比较凌乱,当想要将这个对象传输到另一台机器(RPC)时,不是很方便,所以需要将它序列化。通常将对象变为文件(text)或者二进制流(binary),然后就可以传输,在远端可以重构出来(反序列化)
- 把对象的字节序列永久地保存在硬盘上,通常存放在一个文件中(内存吃不消的情况下)
- 在网络上传送对象的字节序列(RPC),接收方通常需要反序列化将二进制流生成为对象
2、Java中序列化的实现
java.io.ObjectOutputStream
代表对象输出流,它的writeObject(Object obj)
方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。java.io.ObjectInputStream
代表对象输入流,它的readObject()
方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable
和Externalizable
的类的对象才能被序列化,其中Externalizable
接口继承自Serializable
接口,实现Externalizable
接口的类完全由自身来控制序列化的行为,而仅实现Serializable
接口的类可以采用默认的序列化方式 。
对象的序列化步骤如下:
- 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流
- 通过对象输出流的
writeObject()
方法写对象
对象反序列化的步骤如下:
- 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 通过对象输入流的
readObject()
方法读取对象。
3、实现
person类
package serializable;
import java.io.Serializable;
public class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private transient String name;
private String sex;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
测试类
package serializable;
import java.io.*;
/**
* 测试对象的序列化和反序列化
*/
public class TestObjSerializeAndDeserialize {
public static void main(String[] args) {
try {
serializable();
deserializable();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void serializable() throws Exception{
Person person = new Person();
person.setAge(22);
person.setSex("男");
person.setName("Tian xiaoshuai");
ObjectOutputStream ois =
new ObjectOutputStream(new FileOutputStream(new File("C:\\Users\\Txs\\Desktop\\person.txt")));
ois.writeObject(person);
System.out.println("对象序列化成功");
ois.close();
}
private static void deserializable() throws Exception{
File file = new File("C:\\Users\\Txs\\Desktop\\person.txt");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Person person = (Person) ois.readObject();
System.out.println(person.toString());
System.out.println("对象反序列化成功");
}
}
serialVersionUID
作用:
serialVersionUID
适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID
与本地相应实体类的serialVersionUID
进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException
,不定义这个字段的化,JVM会自动加一个
Transient
作用:
控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null