1.简介
(1).序列化
把对象转换为字节序列的过程称为对象的序列化。

(2).反序列化
把字节序列恢复为对象的过程称为对象的反序列化。

(3).为什么要进行序列化或者反序列化
程序在运行时实例化出对象,这些对象存在于内存中,随着程序运行停止而消失,但如果想把某些对象(一般都是各不相同的属性)保存下来或者传输给其它进程,在程序终止运行后这些对象仍然存在,可以在程序再次运行时读取这些对象的信息,或者在其他程序中利用这些保存下来的对象信息恢复成实例对象。这种情况下就要使用对象的序列化和反序列化。

(4).使用场景

  • 需要把内存中的对象保存到文件或者数据库中时
  • 需要通过套接字在网络上传输对象时
  • 需要通过RMI传输对象时

2.序列化
(1).SerializeDemo
ObjectOutputStream类用来序列化一个对象,如下的SerializeDemo例子实例化了一个Employee对象,并将该对象序列化到一个文件中。

public class Employee implements Serializable {
public String name;

public transient int age;

public static String sex;

public final String address = "南京";

/*
* static修饰的sex不能由构造方法初始化
* final修饰的address在定义时必须初始化,因此不需要由构造函数初始化
*/
public Employee(String name, int age) {
this.name = name;
this.age = age;
}

public void sayHello() {
System.out.println("Hello everyone,I am " + name);
}

//get和set方法
}
public class SerializeDemo {
public static void main(String[] args) {
Employee employee = new Employee("steven", 30);
try {
FileOutputStream fileOutputStream = new FileOutputStream("D:\\代码\\project\\app\\src\\employee.ser");
ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
oos.writeObject(employee);
oos.close();
fileOutputStream.close();
System.out.printf("Serialized data is saved in employee.ser");
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}

(2).执行结构

Serialized data is saved in employee.ser

3.反序列化
(1).DeserializeDemo

public class DeserializeDemo {
public static void main(String[] args) {
Employee employee = null;
try {
FileInputStream fileInputStream = new FileInputStream("D:\\代码\\project\\app\\src\\employee.ser");
ObjectInputStream ois = new ObjectInputStream(fileInputStream);
employee = (Employee) ois.readObject();
ois.close();
fileInputStream.close();
} catch (IOException ioException) {
ioException.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee Start......");
System.out.println("name:" + employee.name);
System.out.println("age:" + employee.age);
System.out.println("sex:" + employee.sex);
System.out.println("address:" + employee.address);
employee.sayHello();
System.out.println("Deserialized Employee End......");
}
}

(2).执行结果

Deserialized Employee Start......
name:steven
age:0
sex:null
address:南京
Hello everyone,I am steven
Deserialized Employee End......

4.总结
(1).Serializable
没有实现Serializable接口的类无法序列化,否则会抛以下异常。

java.io.NotSerializableException: Employee
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at SerializeDemo.main(SerializeDemo.java:11)

(2).transient

  • 被transient关键字修饰的属性不会被序列化(不管有没有和static和final联合使用),而是使用该属性类型的默认值,如Employee中被transient关键字修饰的int类型的age,初始化时设置的值为30,反序列化之后值为0。
  • transient只能修饰属性,不能修饰方法和类。

(3).serialVersionUID
serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常InvalidCastException。

(4).static
被static关键字修饰的属性不参与序列化,因为静态变量不是对象的一部分,而是属于类。

(5).final
final变量值参与序列化。