Java序列化流和反序列化流

     序列化流:
        序列化:将一个对象转换成网络中传输的流
            对象输出流:ObjectOutputStream
        反序列化:将网络中传输的流还原成一个对象
            对象输入流:ObjectInputStream

 一个类对象将来要想被序列化,必须要实现Serializable接口,这个接口中没有任何的方法和常量,称为标记接口。

InvalidClassException异常
我们在写完对象后,又修改了类中的内容,又重新写入,再读取的还原对象的时候,报错了InvalidClassException异常
这是因为修改后的UID发生了改变,序列化的对象UID:stream classdesc serialVersionUID = -7948663535168613063, 本地修改后的UID: local class serialVersionUID = 4202380653329948443,  因为没有固定UID,所以每次修改完,UID都会变
解决方案:在Students类里将serialVersionUID写固定,将来谁都不能改,就不会出现修改后错误,不用手写,自动生成即可。
第一步:直接点击异常类

第二步:复制UID

第三步:将复制的UID写入Students类中

第四步:需要重新运行一次程序,只调用write方法,等于将固定UID写入文本中

第五步:修改变量,或者增加其他变量

第六步:修改变量后,只调用read方法,程序也不会报错

总结:序列化对象,要一边修改,一边写入一边读,就不会出现UID不一样的错误

序列化和反序列化使用参考源码:

Students类:
import java.io.Serial;
import java.io.Serializable;

//TODO: 实现序列化需要实现一个Serializable 标记接口(所谓标记接口就是没有任何成员方法和变量,就只是作标记)
//TODO: transient修饰成员变量可以防止被序列化
//    我们在写完对象后,又修改了类中的内容,再读取的还原对象的时候,报错了InvalidClassException

//        stream classdesc serialVersionUID = 2442942279365203766,每次写完UID都会变
//        local class serialVersionUID = 2935475373948736279
//
//  TODO:       解决方案:将serialVersionUID写固定,将来谁都不能改,自动生成即可。
//
//TODO:    若成员不想被序列化存储,使用java提供一个关键字进行修饰 transient
public class Students implements Serializable {
    @Serial
    private static final long serialVersionUID = -4333316296251054416L;
    private String name;
    private int age;
    private String address;
    private  int caiFu;

    public Students() {
    }

    public Students(String name, int age, String address,int caiFu) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public int getCaiFu() {
        return caiFu;
    }

    public void setCaiFu(int caiFu) {
        this.caiFu = caiFu;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", caiFu=" + caiFu +
                '}';
    }
}
测试类:
import java.io.*;
//TODO:关于序列化流,正常写入文本的对象是什么内容,读出来的也就是什么内容,如果临时修改成员方法,并未及时写入原来的文本中
//TODO:这时候再次读就会报错,原因是每次修改后的序列化UID都会发生改变,所以要想正常读出来,则必须固定UID,但是读出来的新的参数的值是默认值,
//TODO:因为没有立即将新内容写入进去。另外被transient修饰的成员变量不会被序列化,就是普通变量,不会对序列化产生影响

//TODO:总结:序列化对象,要一边修改,一边写入一边读,就不会出现UID不一样的错误
public class XuLeiHuaTest {
    public static void main(String[] args) {
//        write();
        read();


    }
    public static void write(){
        //序列化流(输出流)
        ObjectOutputStream ous=null;
        try {
            ous = new ObjectOutputStream(new FileOutputStream("src/main/java/day15_8_13/序列化流.txt"));
            Students s1 = new Students("小伟",18,"山东菏泽",12000);
           ous.writeObject(s1);//将对象序列化
            ous.flush();
        } catch (IOException e) {
           e.printStackTrace();
        }finally {
            try {
                //用完就释放资源
                ous.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void read(){
        //反序列化流(输入流)
        ObjectInputStream ois=null;
        try {
             ois = new ObjectInputStream(new FileInputStream("src/main/java/day15_8_13/序列化流.txt"));
            try {
                Object o = ois.readObject();
                //向下转型
                Students s1 = (Students) o;
                System.out.println(o);

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

        } catch (IOException e) {
           e.printStackTrace();
        }finally {
            //用完释放资源
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我的K8409

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

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

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

打赏作者

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

抵扣说明:

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

余额充值