使用ObjectOutputStream往文本写内容时,首先在文本里面标记开始,然后是内容,最后加上结束标示。如果想再次往文本里面添加内容的话,就要加在开始标示之后和结束标示之前,不然会读取不到写入的内容。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class ObjectBuffer {
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new
                FileOutputStream("src/TXT/Z.txt",false));//工程里面的路径
        oos.writeObject(new User("java",16));
        oos.writeObject(new User("C++",18));
        oos.writeObject(new User("c语言",22));
        oos.writeObject(null);   //最后添加一个空对象,作为后面读取内容的判断
        oos.flush();
        oos.close();
        //第一次使用ObjectOutputStream往文本写内容时,就会自动在文本内容最后打上结束标示。
        //当再次使用ObjectOutputStream往里面写入内容时,内容加在上次内容的后面,当使用ObjectInputStream读取内容时,
        //因为第一次写入内容时,在后面加上了结束标示,将会读取不到第二次写入的内容。

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/TXT/Z.txt"));
        User u;
        while((u = (User) ois.readObject()) != null){
            System.out.println(u);
        }
        ois.close();
    }
}
class User implements Serializable{
    private static final  long  serialVersionUID = 1L;  //序列化
    static int n = 0;
    private String name;
    private int 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;
    }
    public User(String name, int age) {
        super();
        n++;
        this.name = name;
        this.age = age;
    }
    public User() {
        super();
    }
    @Override
    public String toString() {
        n--;
        return "User [name=" + name + ", age=" + age + "]";
    }
}

输出结果:
User [name=java, age=16]
User [name=C++, age=18]
User [name=c语言, age=22]


序列化的概念:
Java序列化机制使用名称为serialVersionUID的long型字段来标志类的版本。序列化对象时,Jvm会把serialVersionUID的值写到类的序列化数据中;反序列化时,JVM会把对象数据数据中的serialVersionUID与本地相应类的serialVersionUID进行比较,如果值不相同(意味着类的版本不同),那么报异常InvalidCastException,即:类版本不对应,不能进行反序列化。如果类版本相同,则可以进行反序列化。


常见的serialVersionUID的值有两种情况:
一种是固定的一个long型值,比如:
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 123L;
第二种是根据类名、接口名、成员方法及属性等生成一个64位的哈希值(ide可以完成此工作),比如:
private static final long serialVersionUID = xxxxL;
当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID值时,Java序列化机制会根据编译的Class生成一个serialVersionUID作序列化版本比较用,一旦class文件有所变动(比如空格、变量名),那么serialVersionUID也会随之变动。


  • 假如A端和B端通信,在A端先把一个对象序列化,在B端进行接收。两端的对象serialVersionUID值是相同的。如果A端增加一个字段,然后序列化,而B端不变,然后反序列化;反序列化正常,但是A端增加的字段丢失(被B端忽略)。
  • 如果B端减少一个字段,A端不变,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。
  • 如果B端增加一个字段,A端不变,反序列化正常,B端增加的字段被赋予初始值。