java中序列化反序列化

遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题

a,什么叫序列化和反序列化

b,作用。为啥要实现这个 Serializable 接口,也就是为啥要序列化

c,serialVersionUID 这个的值到底是在怎么设置的,有什么用。有的是1L,有的是一长串数字,迷惑ing。

 

1、序列化和反序列化的概念

序列化:把对象转换为字节序列的过程称为对象的序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;   

2) 在网络上传送对象的字节序列。

 

2、如何实现序列化

2.1、定义实体类实现Serializable接口

package com.example.dell.serializabledemo;
​
import java.io.Serializable;
​
public class SerializableInfo implements Serializable{
​
//    private static final long serialVersionUID = 1L;
​
    private static int age = 20;
    private String name;
    private String sex;
    //transient:变量修饰符,用transient关键字标记的成员变量不参与序列化过程。
    transient private String address;
​
//    private String addTip;
​
    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 getAddress() {
        return address;
    }
​
    public void setAddress(String address) {
        this.address = address;
    }
​
//    public String getAddTip() {
//        return addTip;
//     }
//
//     public void setAddTip(String addTip) {
//        this.addTip = addTip;
//     }
​
​
    @Override
    public String toString() {
        return "SerializableInfo{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                ", age='" + age + '\'' +
//                ", addTip='" + addTip + '\'' +
                '}';
    }
}
​

 

2.2、main方法

package com.example.dell.serializabledemo;
​
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
​
public class SerializableTest {
​
    public static void main(String[] args) throws Exception {
​
        serialize();
        SerializableInfo info = deserialize();
        System.out.println(info.toString());
​
    }
​
    /*
    * 序列化
    * */
    private static void serialize() throws IOException {
        SerializableInfo serializableInfo = new SerializableInfo();
        serializableInfo.setName("张三");
        serializableInfo.setSex("男");
        serializableInfo.setAddress("北京");
​
        //将serializableInfo对象存储到E盘文件中,完成序列化操作
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:/Serialize.txt")));
        oos.writeObject(serializableInfo);
​
        System.out.println("对象序列化成功");
        oos.close();
    }
​
    /*
     * 反序列化
     * */
    private static SerializableInfo deserialize() throws Exception {
        //读取文件,完成反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/Serialize.txt")));
        SerializableInfo serializableInfo = (SerializableInfo) ois.readObject();
​
        System.out.println("对象反序列化成功");
        return serializableInfo;
    }
​
}

 

运行结果

1、第一种:上面代码直接运行

同时会在E盘下生成Serialize.txt文件

 

 

2、第二种:静态的属性能不能被序列化和反序列化

先序列化对象到文件。这个对象是带静态变量的static。

   public static void main(String[] args) throws Exception {
        serialize();
//        SerializableInfo info = deserialize();
//        System.out.println(info.toString());
    }

现在修改实体类里面age的值,修改为18

然后运行反序列化代码

  public static void main(String[] args) throws Exception {
//        serialize();
        SerializableInfo info = deserialize();
        System.out.println(info.toString());
    }

运行结果

 

可以看到,刚刚序列化的20,没有读出来。读出来的是刚刚修改的18

所以,得出结论,这个静态static的属性,不序列化。

 

3、serialVersionUID 的作用和用法

先是单独执行序列化方法。生成文件。

然后,打开属性 addTip ,再次执行反序列化方法

 

抛异常

解释一下:

因为我再实体类里面是没有明确的给这个 serialVersionUID 赋值,但是,Java会自动的给我赋值的,

这个值跟这个实体类的属性相关计算出来的。

我保存的时候,也就是我序列化的时候,那时候还没有这个addTip属性呢,

所以,自动生成的serialVersionUID 这个值,

在我反序列化的时候Java自动生成的这个serialVersionUID值是不同的,他就抛异常啦。

 

再来一次,就是先序列化,这个时候,把 private static final long serialVersionUID = 1L; 这行代码的注释打开。那个addTip属性先注释掉

序列化之后,再把这个属性打开,再反序列化。

 

 

这个现象对我们有什么意义:

实体类实现了个Serializable接口,但是你没写这个 serialVersionUID 那么在后来扩展的时候,可能就会出现不认识旧数据的bug

所以,得到一个结论,就是在实现这个Serializable 接口的时候,一定要给这个 serialVersionUID 赋值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值