java 21 - 13 IO流之序列化和反序列化

时间:2023-03-08 16:54:32

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)

  构造方法:ObjectInputStream(InputStream in)  创建从指定 InputStream 读取的 ObjectInputStream

反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)

  构造方法:ObjectInputStream(InputStream in)  创建从指定 InputStream 读取的 ObjectInputStream

由于序列化和反序列化的操作对象是类,所以先创建个类:

 package zl_Copy;

 import java.io.Serializable;

 /*
//NotSerializableException:类未序列化异常,所以所要序列话的类要实现Serializable接口 */
public class Animal implements Serializable{ private static final long serialVersionUID = 6425500536266476858L;
private String name;
//private int age;
*      private transient int age; public Animal() {
super();
// TODO Auto-generated constructor stub
} public Animal(String name, int age) {
super();
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Animal [name=" + name + ", age=" + age + "]";
} }

实现类: 

 public class ObjectStreamDemo {

     public static void main(String[] args) throws IOException, ClassNotFoundException {
//由于序列化的对象是个类,所以要首先创建一个类
//序列化方法
//write();
//反序列化
read();
} private static void read() throws IOException, IOException, ClassNotFoundException {
// 创建反序列化对象
//ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt")); //还原序列化对象,不管什么类,反正它父类是Object
Object o = ois.readObject(); //释放资源
ois.close();
//输出结果到控制台看看
System.out.println(o);
//Animal [name=萨摩耶, age=2] } private static void write() throws IOException {
//创建序列化对象
//ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.txt")); //创建所要序列化的类的对象
Animal a = new Animal("萨摩耶",2); //写入序列化对象中,注意,写入的是类
oos.writeObject(a); //释放资源
oos.close(); //java.io.NotSerializableException
//NotSerializableException:类未序列化异常,所以所要序列话的类要实现Serializable接口
} }

注意:

private static final long serialVersionUID = 6425500536266476858L;:
为什么要写这个?如果不写这个,若是更改了类里面的变量,如:
 private int age;
改为:
int age;

若是这样更改了以后,就必须重新进行序列化,不然就会出现错误:

java.io.InvalidClassException: cn.itcast_07.Person; local class incompatible: stream classdesc serialVersionUID = -2071565876962058344, local class serialVersionUID = -8345153069362641443

为什么会有问题呢?
  Person类实现了序列化接口,那么它本身也应该有一个标记值。
  先把这个标记值假设是100。
   开始的时候:
    Person.class -- id=100
    wirte数据: oos.txt -- id=100
    read数据: oos.txt -- id=100

  更改了age以后:
    Person.class -- id=200
    wirte数据: oos.txt -- id=100
    read数据: oos.txt -- id=100
我们在实际开发中,可能还需要使用以前写过的数据,但是不能重新写入。
所以,我们要让这个id值在java文件中设为一个固定的值,这样,修改文件的时候,这个id值就不会发生改变。
方法是:看到类名处有黄色警报线,点击鼠标即可。

 private transient int age;

一个类中可能有很多的成员变量,但是有些变量不想进行序列化。
方法:使用transient关键字声明不需要序列化的成员变量