IDEA设置自动生成serialVersionUID,解决在对象流进行读写操作时所引发的问题,NotSerializableException,附实验结果及操作流程

1、序列化是什么?

       序列化是一种处理对象流的机制,所谓对象流就是将对象的内容进行流化。可以对流化的对象进行读写操作,也可以将流化的对象传输于网络之间。序列化是为了解决在对象流进行读写操作是所引发的问题。

       把内存里面的这些对象给变成一连串的字节描述的过程。如: 文件保存

2、 序列化的实现以及反序列化

      将需要被序列化的类实现Serializable接口,该接口没有需要重写的方法。

implements Serializable

implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流来构造一个ObjectOutputStream(对象流),接着,ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存期状态),使用输入流ObjectInputStream对象的方法readObject() 从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。<——输入流进行原对象恢复!

注意:1、静态变量不会被序列化的,它可不在堆内存中,序列化只会序列化堆内存的数据

           2、transient 修饰的属性,是不会被序列化的

序列化时最好是定义序列化版本id  即 public  static  final  Long  seriaVersionUID  =  1L (默认)  或者 xxxxx L(自定义64位都行)

3、自动生成serialVersionUID

3.1 IDEA设置

3.1.1 快捷键:Ctrl+Shift+S 进入设置

3.1.2 步骤ABCD;

3.1.3 步骤C 搜索:serialVersionUID

3.2 光标移到类文件的类名上(类必须实现Serializable接口),按快捷键Alt + Enter 出现 Add 'serialVersionUID' Field

4、序列化

/**
 * @Author: Be.insighted
 * Description:
 * @date Create on 2020/8/12 16:40
 **/
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private static String sex = "男";

    private int age;



    private String name;

    transient private String adress;

    public static String getSex() {
        return sex;
    }

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

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", adress='" + adress + '\'' +
                ", sex=" + sex +
                '}';
    }


}

序列化并反序列化:

/**
 * @Author: Be.insighted
 * Description:
 * @date Create on 2020/8/12 16:45
 **/
public class TestSerializable {

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

        serialized();
        Person person = deSerialized();
        System.out.println("反序列化: " + person);

    }

    private static void serialized() throws IOException{
        Person person = new Person();
        person.setAdress("济源市");
        person.setAge(18);
        person.setName("特朗普");
        System.out.println("序列化: " + person);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/person.txt")));
        oos.writeObject(person);
        System.out.println("对象序列化成功!");
        oos.close();

    }

    private static Person deSerialized() throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/person.txt")));
        Person person = (Person)ois.readObject();
        System.out.println("字节流反序列化成功!");
        ois.close();

        return person;

    }


}

结果:

生成文件:

代码仅注释掉 // erialized(); 以及 将person的 sex = "女"; 运行,看输出:

竟然:sex = 女 !!! 说明,类变量不会被序列化!!!

5、反序列化:

transient修饰的属性没有被序列化,反序列化的时候无值 <------- adress的值 'null'

NotSerializableException <------ 解决: 请给对应的类实现序列化

如果没有显示的声明 serialVersionUID 的值,Java会自动的给我赋值的,这个值跟这个对象的属性相关计算出来的。

6、实现这个Serializable 接口的时候,一定要给这个 serialVersionUID 赋值

“serialVersionUID” 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID。

没写这个 serialVersionUID ,扩展的时候可能就会出现不认识旧数据的bug!!!

7、不是Java编译器会自动生成么?那为什么还要显示声明呢?

为了避免在到处运行时出现不一致问题,保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。

8、子类实现序列化,父类没有实现,子类可以实现序列化么?

如果父类没有声明无参构造函数,实现序列化失败!

9、类中存在引用对象,那么这个类在什么情况下能够序列化?

类中的所有属性都必须是可以序列化的,这个类才能序列化。

10、同一个对象多次序列化(中间有属性更新),会影响序列化么?

同一个对象多次序列化,Java8不会为这个对象进行多次序列化。序列化会有一个独一无二的编码号,再次序列化的时候校验到该编码号则不会再序列化!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值