ObjectOutputStream和ObjectInputStream用于存储和读取基本数据类型数据和对象数据的处理流,
它的强大之处就是可以将Java对象写入到数据源中,也能把数据从数据源中还原出来。
序列化:用ObjectOutputStream类保存基本数据类型或对象的机制。
反序列化:用ObjectInputStream类读取基本数据类型或对象的机制。
ObjectOutputStream和ObjectInputStream不能序列化Static和transient修饰的成员变量。
实体类实例化的条件:
一:实现Serializable接口。
二:当前类提供一个全局变量serialVersionUID,代表版本号。
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
public static final long serialVersionUID = 42322233232L;
serialVersionUID用来表明类的不同版本间的兼容性,简而言之,其目的是以序列化对象进行版本控制,有关各版本序列化是否兼容,如果没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的,若类的变量做了修改,serialVersionUID可能发生变化,因此建议显示声明。
Java序列化机制是通过在运行时判断类的serialVersionUID来验证版本的一致性的,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现版本不一致的异常。
序列化机制:
对象序列化机制允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流就可以恢复成原来的Java对象。
代码实现:
/**
* 实体类
*/
public class Person implements Serializable {
//序列版本号
public static final long serialVersionUID = 42322233232L;
private Integer id;
private String name;
private Integer age;
private String address;
public Person() {
}
public Person(Integer id, String name, Integer age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
序列化过程:将内存中的对象保存到磁盘中
/**
* 序列化过程:将内存中的对象保存到磁盘中
* ObjectOutputStream的使用
*/
@Test
public void test1() {
//创建对象输出流
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//将集合数据写入文件
oos.writeObject(list);
oos.flush();
//将实体类数据写入文件,(实体类需要实现Serializable接口)
Person p1 = new Person( 1, "张三", 18, "中国");
//写入实体类对象数据
oos.writeObject(p1);
//刷新数据
oos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
反序列化过程:将磁盘中的对象读取到内存中
/**
* 反序列化过程:将磁盘中的对象读取到内存中
* ObjectInputStream的使用
*/
@Test
public void test2() {
//创建对象输入流
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.dat"));
//读取数据的顺序和写入的顺序一致
//读取集合数据
Object o = ois.readObject();
List<Integer> list = (List<Integer>) o;
System.out.println(list);
//读取实体类数据
Object o1 = ois.readObject();
Person p1 = (Person) o1;
System.out.println(p1);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
测试结果:
[1, 2, 3]
Person{id=1, name='张三', age=18, address='中国'}