java_序列化

Posted qrrlinux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java_序列化相关的知识,希望对你有一定的参考价值。

1.概念

序列化:将对象转化为字节序列的过程

反序列化:将字节序列转化为对象的过程

用途:

A:将对象转化为字节序列保存在硬盘上,如文件中,如文本中的例子就是将person对象序列化成字节序列,存在person.txt文件中

B:网络传输中一般都是以对象序列化的形式存在,在网络的发送/接收两端进行对象的序列化/反序列化

输入/输出的使用:

一般都是针对内存而言,内存--硬盘--》outputStream     从硬盘--内存--》inputStream

具体使用要根据场景来确定

2.example

2.1 无显式的指定UID,采用编译系统自动生成的

Object:

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

    private int age;

    private String name;

    private String sex;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Person{");
        sb.append("age=").append(age);
        sb.append(", name=‘").append(name).append(‘‘‘);
        sb.append(", sex=‘").append(sex).append(‘‘‘);
        sb.append(‘}‘);
        return sb.toString();
    }
}

 object  uid

package com.java.baseinfo.knowledge.code.serializable;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class TestObjSerializeAndDeserialize {

    public static void main(String[] args) {
        // 序列化
        SerializablePerson();
        // 反序列化
        //Deserialization();
    }

    private static void SerializablePerson() {
        Person person = new Person();
        person.setAge(10);
        person.setName("测试");
        person.setSex("女");

        String path = "src/test/resources/person.txt";

        try {
            FileOutputStream fileOutputStream = new FileOutputStream(new File(path));

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

            objectOutputStream.writeObject(person);

            System.out.println("序列化成功");
            fileOutputStream.close();
            objectOutputStream.close();

        } catch (FileNotFoundException e) {
            System.out.printf("FileNotFoundException====>" + e);
        } catch (IOException e) {
            System.out.printf("IOException====>" + e);
        }
    }

    private static Person Deserialization() {

        try {
            FileInputStream fileInputStream = new FileInputStream(new File("src/test/resources/person.txt"));

            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

            Person person = (Person) objectInputStream.readObject();

            System.out.printf("Deserialization.person===>"+person);

        } catch (FileNotFoundException e) {
            System.out.printf("FileNotFoundException====>" + e);
        } catch (IOException e) {
            System.out.printf("IOException====>" + e);
        } catch (ClassNotFoundException e) {
            System.out.printf("ClassNotFoundException====>" + e);
        }
        return null;
    }
}

先序列化,才进行反序列化

Deserialization.person===>Person{age=10, name=‘测试‘, sex=‘女‘} 

给person增加字段,再用原来的序列化后的结果,进行反序列化;

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;
public class Person implements Serializable { private int age; private String name; private String sex; // 增加字段测试序列化 private String addText; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddText() { return addText; } public void setAddText(String addText) { this.addText = addText; } @Override public String toString() { final StringBuffer sb = new StringBuffer("Person{"); sb.append("age=").append(age); sb.append(", name=‘").append(name).append(‘‘‘); sb.append(", sex=‘").append(sex).append(‘‘‘); sb.append(", addText=‘").append(addText).append(‘‘‘); sb.append(‘}‘); return sb.toString(); } }

 运行结果

IOException====>java.io.InvalidClassException: com.java.baseinfo.knowledge.code.serializable.Person; local class incompatible: stream classdesc serialVersionUID = 6964452789008335213, local class serialVersionUID = -3534890433624150186
Process finished with exit code 0  

 原因是:之前代码中未显示的指定UID,当Object中新增字段时,编译器又新生成一个UID,于是出现序列化版本不一致的问题;

2.2 显式指定UID

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

    private static final long serialVersionUID = -3534890433624150186L;
    private int age;

    private String name;

    private String sex;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Person{");
        sb.append("age=").append(age);
        sb.append(", name=‘").append(name).append(‘‘‘);
        sb.append(", sex=‘").append(sex).append(‘‘‘);
        sb.append(‘}‘);
        return sb.toString();
    }
}

运行上述main函数, 先进行序列化,然后再对object增加属性,再序列化的结果,进行反序列化

package com.java.baseinfo.knowledge.code.serializable;

import java.io.Serializable;

public class Person implements Serializable {

    private static final long serialVersionUID = -3534890433624150186L;
    private int age;

    private String name;

    private String sex;

    // 增加字段测试序列化
    private String addText;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddText() {
        return addText;
    }

    public void setAddText(String addText) {
        this.addText = addText;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Person{");
        sb.append("age=").append(age);
        sb.append(", name=‘").append(name).append(‘‘‘);
        sb.append(", sex=‘").append(sex).append(‘‘‘);
        sb.append(", addText=‘").append(addText).append(‘‘‘);
        sb.append(‘}‘);
        return sb.toString();
    }
}

反序列化结果,新增的字段为空值

Deserialization.person===>Person{age=10, name=‘测试‘, sex=‘女‘, addText=‘null‘}
Process finished with exit code 0 

显式的指定UID,目前常用到的场景是:当object增加的字段时候,不希望反序列化出现异常,即希望类的不同版本对序列化兼容;

等用到其他场景的时候,再更新。。

参考:https://www.cnblogs.com/xdp-gacl/p/3777987.html

以上是关于java_序列化的主要内容,如果未能解决你的问题,请参考以下文章

编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议11~15)

这些 C++ 代码片段有啥作用?

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

VSCode 配置 用户自定义代码片段 自定义自动代码补充

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

[AndroidStudio]_[初级]_[配置自动完成的代码片段]