java序列化与反序列化和serialVersionUID

简单介绍下序列化

序列化

将java中的对象以文件的形式保存到硬盘服务器中的过程称之为序列化

序列化主要作用

1、将对象保存成文件,方便之后反序列化获取文件中的对象

2、网络编程中远程传输对象

ObjectOutputStream 序列化类

ObjectInputStream 反序列化类

序列化注意事项:

所有序列化对象必须是实现了java.io.Serializable接口

定义:

    Java序列化就是指把Java对象转换为字节序列的过程(生成了一个打开是乱码的二进制文件)

    Java反序列化就是指把字节序列恢复为Java对象的过程。

serialVersionUID

      一个对象数据,在反序列化过程中,如果序列化串中的serialVersionUID与当前对象值不同,则反序列化失败,否则成功。

如果serialVersionUID没有显式生成(使用系统默认生成的),系统就会自动生成一个。生成的输入有:类名、类及其属性修饰符、属性、构造器...。任何一项的改变都会导致serialVersionUID变化,也就是说只要你的class类中有一丢丢变化你都无法反序列化出来。

属性的变化都会导致自动生成的serialVersionUID发生变化。例如,对于对象A,我们生成序列化的S(A),然后修改A的属性,则此时A的serialVersionUID发生变化。反序列化时,S(A)与A的serialVersionUID不同,无法反序列化。会报序列号版本不一致的错误。为了避免这种问题, 一般都会要求实现serialiable接口的类显式的声明一个serialVersionUID。

例子

对于一个类

public class Dog extends Animal{

    private int tooth;

    public Dog() {
    }

    public Dog(String name, int weight, int tooth) {
        super(name, weight);
        this.tooth = tooth;
}

}

一个抽象类

public abstract class Animal implements Serializable {

    private String name;
    private int weight;

    public Animal() {
    }

    public Animal(String name, int weight) {
        this.name = name;
        this.weight = weight;
}

}
Dog继承了Animal抽象类,Animal实现了序列化接口,那么Dog也相当于实现了序列化接口

测试:

目前有两个方法

serializable()序列化,
unserializable()反序列化
public static String serializable(Object o){
    try {
        File file = new File("e:/pet.obj");
        if(!file.exists()){
            file.createNewFile();
        }
        ObjectOutputStream out =
                new ObjectOutputStream(
                        new FileOutputStream(file));
        out.writeObject(o);
        out.close();
        return "成功";
    } catch (Exception e) {
        e.printStackTrace();
        return "失败";
    }
}

public static Object unserializable(){
    try {
        File file = new File("e:/pet.obj");
        if(!file.exists()){
            serializable(new ArrayList<Animal>());
        }
        ObjectInputStream in =
                new ObjectInputStream(
                        new FileInputStream(file));
        return in.readObject();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

我们在main方法中调用序列化一个类

public static void main(String[] args) {
    String 陈dog = SerializableUtil.serializable(new Dog("陈dog", 300, 3));

System.out.println(陈dog);

}

查看控制台

图片

然后反序列化并输出控制台

 public static void main(String[] args) {
    Animal unserializable = (Animal) unserializable();

System.out.println(unserializable);

}

控制台反序列化成功

图片

此时我们用的是隐式serialVersionUID,也就是自己没声明

然后我们去修改下类在试试反序列化

我们给Animal类加一个属性

private int a;

再次反序列化

图片

我们可以看到serialVersionUID不正确,也就是上面说的类中修改之后这个值就会变化,无法反序列化,下面我们显式声明一个;

get序列化类Animal新加一个serialVersionUID

private static final long serialVersionUID = 1L;

然后重复如上操作,会发现修改Animal属性之后我们也能反序列化的到对象~~

完结  干饭去咯

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只java小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值