Java序列化和反序列化

原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11804649.html

Java中的对象序列化意思也就是说用来存储或者传输Java对象, 反序列化就是将存储起来的Java对象或者传输过来的流转化为Java对象的操作,具体的序列化操作和注意事项如下:

 首先创建一个普通的Java对象, 不实现java.io.Serializable接口;

/**
 * 普通的Java对象 (未实现java.io.Serializable接口)
 */
public class SerializableModel{
    
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

main测试类如下:

/**
 * main测试类
 */
public class MainTest {

    public static void main(String[] args) throws Exception{
        serialObj();
    }

    /**
     * 序列化操作
     * @throws IOException
     */
    public static void serialObj() throws IOException {
        SerializableModel model = new SerializableModel();
        model.setId("33333");
        FileOutputStream fileOutputStream = new FileOutputStream("d://tmp/test.txt");
        ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
        outputStream.writeObject(model);
        outputStream.close();
        fileOutputStream.close();
    }

    /**
     * 反序列化操作
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void unserialObj() throws IOException, ClassNotFoundException {
        SerializableModel model = null;
        FileInputStream fileInputStream = new FileInputStream("d://tmp/test.txt");
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
        model = (SerializableModel) inputStream.readObject();
        inputStream.close();
        fileInputStream.close();
        System.out.println(model.getId());
    }
}

执行序列化方法, 此时会抛出序列化异常,如下:

 这是因为没有实现java.io.Serializable接口, Java规定需要序列化的类都需要实现该接口, 表示对象可序列化, 没有任何方法需要实现, 仅仅是作为一个标识, 接下来我们再实现这个接口:

/**
 * 普通的Java对象(实现序列化接口)
 */
public class SerializableModel implements Serializable {

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

继续执行main方法中的序列化方法, 执行成功, 生成的文本如下:

� sr exception.SerializableModel?nQヱ L idt Ljava/lang/String;xpt 33333

这个应该是保存下来的字节码文件, 可以看到JavaBean的名称和属性id以及属性值33333.

接下来我们再给Java对象加上一个序列化版本号:

/**
 * 普通的Java对象(实现序列化接口, 带序列化版本号)
 */
public class SerializableModel implements Serializable {

    private static final long serialVersionUID = 0L;

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

我们再把main方法中的serialObj()方法替换成反序列化方法unserialObj()试试看:

public static void main(String[] args) throws Exception{
        unserialObj();
    }

 可以看到, 抛出了异常信息, 意思大概就是从流中读取的类描述信息看到的序列化版本号是-2017031617106284276(这个版本号是Java自动生成的, 因为没有指定版本号, 会自动生成一个), 而我们自己定义的序列化版本号是0, 版本不相同, 不能进行转化,所以报错.

我们把版本号去掉再试试看:

 此时通过了编译并且打印了Java对象的id.

  总结, Java对象序列化是为了传输或者存储Java对象的, 需要序列化的对象必须实现java.io.Serializable接口, 尽量设置一个序列化版本号并且在修改了Java对象属性的时候手动去修改版本号避免反序列化的时候由于属性缺失造成转化出来的Java对象不完整而导致不必要的业务逻辑处理失败事件.

原文地址:https://www.cnblogs.com/fanerwei222/p/11804649.html