1. 理解序列化与反序列化

Java产品序列号生成 java序列化版本号_Java产品序列号生成

2. 序列化的实现

!!! 参与序列化和反序列化的对象必须实现Serializable接口
标志接口,里面没有实现方法,是给java虚拟机参考的。java虚拟机会自动为该类生成一个序列化版本号
Q:那么序列化版本号有什么用呢???
A:用来区分类

package bean;

import java.io.Serializable;

public class Student implements Serializable {
    private int no;
    private String name;

    public Student() {
    }

    public Student(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

序列化:

import bean.Student;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectOutputStream01 {
    public static void main(String[] args) throws IOException {
        Student s = new Student(111,"zhangsan");
        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
        oos.writeObject(s);

        oos.flush();
        oos.close();

    }
}

反序列化:

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputStreamTest01 {
    public static void main(String[] args) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
        Object obj = ois.readObject();
        System.out.println(obj);//反序列化回来是一个学生对象,所以会调用学生对象的toString() 方法
        ois.close();
    }
}

3.一次序列化和反序列化多个对象

解决方案:将对象放到集合里面
序列化:

import bean.User;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class ObjectOutputStreamTest02 {
    public static void main(String[] args) throws Exception {
        List<User> userList = new ArrayList();
        userList.add(new User(1,"shangsan"));
        userList.add(new User(2,"lisi"));
        userList.add(new User(3,"wangwu"));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users"));
        
        oos.writeObject(userList);
        oos.flush();
        oos.close();
        

    }
}

反序列化:

import bean.User;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ObjectInputStreamTest02 {
    public static void main(String[] args) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users"));
//        Object obj = ois.readObject();
        List<User> userList = (List<User>)ois.readObject();
        for(User user:userList){
            System.out.println(user);
        }
        ois.close();

    }
}

4. 不希望某个对象的属性参与序列化:transient

Java产品序列号生成 java序列化版本号_java_02

5. 关于序列化版本号:

事件发生背景:

一开始声明了一个类,对其进行序列化和反序列化后,过了很长一段时间(十年),

这个类被改动了,之后需要重新编译,编译之后生成了全新的字节码文件,并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变。这个时候再去执行之前的反序列化文件,不执行序列化,因为之前就序列化过了,会有如下报错:

Java产品序列号生成 java序列化版本号_Java产品序列号生成_03


无效的类异常,流里面的序列化版本号和本地的序列化版本号不一致。

总结:
1).java语言中采用什么机制来区分类的?
首先:通过类名
其次:如果类名一样,再通过序列化版本号

Java产品序列号生成 java序列化版本号_java_04


2). 自动序列化版本号的缺陷:

一旦代码确定之后,不能进行后续的修改,只要一修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java虚拟机会认为是一个全新的类。

【改进】将序列化版本号手动写出来,不建议自动生成

也可以使用IDEA工具

Java产品序列号生成 java序列化版本号_Java产品序列号生成_05

6. IO和Properties联合使用

IO流:文件的读和写。

Properties:是一个Map集合,key和value都是String类型。

Java产品序列号生成 java序列化版本号_java_06


Java产品序列号生成 java序列化版本号_Java产品序列号生成_07

经常变动的数据只需放入文件中,使用程序动态读取,将来只需要改动文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。