Java中自定义异常类以及对象流自定义类中为什么要声明一个全局常量?

问题描述

在开发中我们会经常使用自定义异常类,或者使用对象流,在自定义异常类中,我们需要继承ExceptionRuntimeException,并且需要提供serialVersionUID的属性,而在使用对象流中自定义类需要实现Serializable(标识)接口,也同要需要提供一个serialVersionUID的属性,那么这是为什么呢?让我们看一下源码:


1.Exception类中的serialVersionUID属性

Exception类中的serialVersionUID属性


2.Serializable接口中的注释

Serializable接口中的注释

提示:其实在Serializable接口的注释中已经对问题进行了解释,但是我们留到后面去说

错误演示:

我们先演示如果不按照规则进行会出现什么问题。
注意:开发中,需要使用try-catch-finally方式处理流的异常

1.我们随便定义一个JavaBean

import java.io.Serializable;

public class Person implements Serializable {//Serializable:属于一个标识接口
    transient String name;
    static int age;
    int id;
//    String nationality = "China";//国籍

//    static final long serialVersionUID = 423216156564656L;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public int getId() {
        return id;
    }

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

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

2.再定义一个测试类

import org.junit.Test;

import java.io.*;

public class PersonTest {

    /**
     * 演示自定义类的对象的序列化和反序列化过程
     * 序列化过程
     */
    @Test
    public void test1() throws IOException {
        //1.创建File类的对象
        File file = new File("object.txt");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));

        //2.写出数据即为序列化过程
        Person p1 = new Person("Tom", 18);
        oos.writeObject(p1);
        oos.flush();

        Person p2 = new Person("Jerry", 23, 1221);
        oos.writeObject(p2);
        oos.flush();

        //3.关闭资源
        oos.close();
    }

    /**
     * 演示自定义类的对象的序列化和反序列化过程
     * 反序列化过程
     */
    @Test
    public void test2() throws IOException, ClassNotFoundException {
        //1.创建File类的对象
        File file = new File("object.txt");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));

        //2.读取文件中的对象(或反序列化的过程)
        Person person = (Person) ois.readObject();
        System.out.println(person);

        Person person1 = (Person) ois.readObject();
        System.out.println(person1);

        //3.关闭资源
        ois.close();
    }
}

先运行test1
test1运行结果再运行test2
test2运行结果

test1中我们将数据写入到Objtct.txt类中,再通过test2反序列化将Objtct.txt中的数据转换成对象流,可以看到运行结果没有问题,非常正常,这是因为在序列化过程中,会自动给自定义类创建一个serialVersionUID,而在反序列化中也会使用这个id来找到这个类进行反序列化,而我们一旦对原本的Person类进行修改(将国籍属性取消注释),那么再次运行又会重新生成一个serialVersionUID,从而导致原有的Objtct.txt中的数据因为找不到原来的serialVersionUID而不能再转换成对象流。


将国籍注释打开
在这里插入图片描述

再次运行test2从Objtct.txt读取文件中的对象
在这里插入图片描述
可以看到报错信息显示:

java.io.InvalidClassException: java05_objectstream.demo.Person; local class incompatible: stream classdesc serialVersionUID = 1027002611310758675, local class serialVersionUID = -135851562499732227

意思是:
本地类不兼容:
流classdesc serialVersionUID = 1027002611310758675,
本地类serialVersionUID = -135851562499732227
因为对象流中保存的serialVersionUID 与本地类的serialVersionUID 不一致导致


显示定义serialVersionUID :

static final long serialVersionUID = 423216156564656L;//数值随便输

如果声明了serialVersionUID,即使在序列化完成之后修改了类导致类重新编译,则原来的数据也能正常反序列化,只是新增的字段值是默认值而已。

在这里插入图片描述

总结

static final long serialVersionUID = 42L;

无论是自定义异常类还是对象流自定义类,都建议显式声明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Leighteen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值