博客
关于我
day19Java-其它IO-ObjectIn(Out)putStream-(反)序列化流
阅读量:268 次
发布时间:2019-03-01

本文共 6201 字,大约阅读时间需要 20 分钟。

博客名称

文章目录

ObjectIn(Out)putStream-(反)序列化流

java.io.InputStream 继承者 java.io.ObjectInputStream

java.io.OutputStream 继承者 java.io.ObjectOutputStream

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)

ObjectOutputStream-序列化流

将Person转为流的时候出现异常:NotSerializableException: com.ginger.demo01.Person

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。

原因是:如果一个对象,转化为一个流(进行网络传输)必须要实现Serializable标记接口,在这里Person没有实现所以报改错,所以得加上

代码演示

public class ObjectInputStreamDemo {       public static void main(String[] args) throws IOException, ClassNotFoundException {           //写        writer();    }    public static void writer() throws IOException {           //创建序列化流对象        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));        //创建Perion对象        Person p = new Person("格雷福斯", 40);        //对象--流数据--oos.txt        oos.writeObject(p);        oos.close();    }}

实体类

//实现Serializable接口就可以进行网络传输public class Person implements Serializable{       private String name;    private int age;    public Person(String name, int age) {           this.name = name;        this.age = age;    }    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;    }}

结果:没实现接口之前

Exception in thread "main" java.io.NotSerializableException: com.ginger.demo01.Person	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)	at com.ginger.demo01.ObjectInputStreamDemo.writer(ObjectInputStreamDemo.java:24)	at com.ginger.demo01.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:8)

ObjectInputStream-反序列化流

在第一次读取的时候没有报错,直接输出Person对象的时候,打印的是地址值,看得不是很方便,所以我在Person重写了toString方法此时报错了。InvalidClassException: com.ginger.demo01.Person; local class incompatible: stream classdesc serialVersionUID = 311183030272692197, local class serialVersionUID = 6499259360078010285为什么第一次读取不出现异常,在Person重写toString方法的时候在读取,就出现上述异常?	原因:Person类实现了序列化接口Serializable,那么它本身也因该有一个标记值。	假设该标记值为1000。		Person.class -- 序列化id=1000	(把java文件编译成class文件)		writer数据 -- oos.txt  -- 序列化id该是=1000		read数据 -- oos.txt -- 反序列化id也是=1000		所以我第一次读取的时候没有抛出异常		因为输出的是地址值,重写Person的toString方法,也正是因为修改了Person方法。		Person.class -- 此时序列化id=2000	(把java文件重新编译成class文件)		writer数据 -- oos.txt -- 因为还是以前的文件,序列化id就是=1000 (此时的writer方法我已经注释了,没有重新写到文件)		read数据 -- oos.txt -- 所以读取的也还是以前的文件,序列化就是=1000出现该异常要怎么解决?	修改Person过后,重新写文件,重新读文件。(这样有一个问题,就是以前读的数据被覆盖了?)		在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?		通过异常信息可以看出来,报错原因是因为id值不匹配,修改Perons类后,没有重新写数据,表示这里读取的数据就是以前的,然后把文件中以前的Person的序列化id和现在Person序列化id做比较发现不一样,所以报错。		如果我有办法,让这个id值在java文件中是一个固定的值,这样,在修改java文件的时候,这个id值就不会发生改变了。		怎么获取到这个ID值呢?		eclipse:实现序列化接口的时候会出现一个黄色警告线,点击提示中的两个其中一个即可。		在IDEA里面需要安装一个插件,这个在网上找就可以了。安装好后使用快捷键Alt+insert就可以了,自动生成。					private static final long serialVersionUID = 6499259360078010285L;		要知道的是:		序列化id:private static final long serialVersionUID = 6499259360078010285L;		产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。(读取还是以前的信息,不是改变过后的。)注意:		我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?		使用transient关键字声明不需要序列化的成员变量

代码演示

public class ObjectInputStreamDemo {       public static void main(String[] args) throws IOException, ClassNotFoundException {           //写        //writer();        //读        reader();    }    public static void reader() throws IOException, ClassNotFoundException {           //创建反序列化流对象        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));        //oos.txt--流数据--对象        Object p = ois.readObject();//        System.out.println(p);    }    public static void writer() throws IOException {           //创建序列化流对象        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));        //创建Perion对象        Person p = new Person("格雷福斯", 40,"100");        //对象--流数据--oos.txt        oos.writeObject(p);        oos.close();    }}

实体类

public class Person implements Serializable {       //自动生成序列化id    private static final long serialVersionUID = 6499259360078010285L;    private String name;    private int age;    private String chinese;    public String getChinese() {           return chinese;    }    public void setChinese(String chinese) {           this.chinese = chinese;    }    public Person(String name, int age, String chinese) {           this.name = name;        this.age = age;        this.chinese = chinese;    }    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;    }    @Override    public String toString() {           return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                ", chinese='" + chinese + '\'' +                '}';    }}

结果:

Person{   name='格雷福斯', age=40, chinese='100'}

修改实体类,chinese这个字段我不想被序列化,重新写读。

public class Person implements Serializable {       //自动生成序列化id    private static final long serialVersionUID = 6499259360078010285L;    private String name;    private int age;    //transient:chinese我不想被序列化    private transient String chinese;    public String getChinese() {           return chinese;    }    public void setChinese(String chinese) {           this.chinese = chinese;    }    public Person(String name, int age, String chinese) {           this.name = name;        this.age = age;        this.chinese = chinese;    }    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;    }    @Override    public String toString() {           return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                ", chinese='" + chinese + '\'' +                '}';    }}

结果:从结果看到chinese值已经看不到了

Person{   name='格雷福斯', age=40, chinese='null'}

转载地址:http://hlya.baihongyu.com/

你可能感兴趣的文章
MySQL 错误
查看>>
mysql 随机数 rand使用
查看>>
MySQL 面试题汇总
查看>>
MySQL 面试,必须掌握的 8 大核心点
查看>>
MySQL 高可用性之keepalived+mysql双主
查看>>
mysql 默认事务隔离级别下锁分析
查看>>
Mysql--逻辑架构
查看>>
MySql-2019-4-21-复习
查看>>
mysql-5.7.18安装
查看>>
MySQL-Buffer的应用
查看>>
mysql-cluster 安装篇(1)---简介
查看>>
mysql-connector-java各种版本下载地址
查看>>
mysql-EXPLAIN
查看>>
mysql-group_concat
查看>>
MySQL-redo日志
查看>>
MySQL-【1】配置
查看>>
MySQL-【4】基本操作
查看>>
Mysql-丢失更新
查看>>
Mysql-事务阻塞
查看>>
Mysql-存储引擎
查看>>