博客
关于我
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 为某个字段的值加前缀、去掉前缀
查看>>
mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
查看>>
mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
查看>>
mysql 主键重复则覆盖_数据库主键不能重复
查看>>
Mysql 优化 or
查看>>
mysql 优化器 key_mysql – 选择*和查询优化器
查看>>
MySQL 优化:Explain 执行计划详解
查看>>
Mysql 会导致锁表的语法
查看>>
mysql 使用sql文件恢复数据库
查看>>
mysql 修改默认字符集为utf8
查看>>
Mysql 共享锁
查看>>
MySQL 内核深度优化
查看>>
mysql 内连接、自然连接、外连接的区别
查看>>
mysql 写入慢优化
查看>>
mysql 分组统计SQL语句
查看>>
Mysql 分页
查看>>
Mysql 分页语句 Limit原理
查看>>
MySQL 创建新用户及授予权限的完整流程
查看>>
mysql 创建表,不能包含关键字values 以及 表id自增问题
查看>>