对象序列化流与对象反序列化流(ObjectOutputStream,ObjectInputStream)
这个连接包含了常用的流------IO流(总篇章)
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
字节序列写到文件后,相当于文件中持久保存了一个对昂的信息
反之。该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
要实现序列化与反序列化,就要使用对象序列化流和对象反序列化流:
- 对象序列化流:ObjectOutputStream
- 对象反序列化流:ObjectInputStream
对象序列化流:ObjectOutputStream
- 将Java对象的原始数据类型和图像写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网络套接字流,则可以再另外一个主机上或另一个进程中重构对象
- 构造方法:ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
- 序列化对象的方法:void writeObject(Object obj):将指定的对象写入ObjectOutputStream
下面我们放代码演示
学生类
package com.testIO;/*** @author 林高禄* @create 2020-05-12-21:39*/
public class Student {private String name;private int age;public Student() {}public Student(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;}
}
序列化Demo
package com.testIO;import java.io.*;/*** @author 林高禄* @create 2020-05-10-13:11*/
public class ObjectOutputStreamDemo {public static void main(String[] args) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test//src//com//testIO//oos.txt"));Student s = new Student("林高禄",27);oos.writeObject(s);oos.close();}
}
运行出现以下错误:
Exception in thread "main" java.io.NotSerializableException: com.testIO.Student
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.testIO.ObjectOutputStreamDemo.main(ObjectOutputStreamDemo.java:13)
NotSerializableException
抛出一个实例需要Serializable接口。序列化运行时或实例的类可能会抛出此异常
Serializable
类的序列化由实现java.io.Serializable接口的类启用。不实现此接口的类将不会使任何状态序列化或反序列化。可序列化类的所有子类型都是可序列化的。序列化接口没有方法或字段,仅用于标识可串行化的语义。
到这里我们就明白报 java.io.NotSerializableException: com.testIO.Student异常的原因是,学生类Student没有实现Serializable接口,下面我们把Student代码修改一下,去实现Serializable接口。
package com.testIO;import java.io.Serializable;/*** @author 林高禄* @create 2020-05-12-21:39*/
public class Student implements Serializable {private String name;private int age;public Student() {}public Student(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;}
}
再次运行,得到oos.txt文件含有一下内容
到这里,说明我们的序列化成功
注意:
- 一个对象要想被序列化,该对象所属的类必须实现Serializable接口。
- Serializable是一个标记接口,实现该接口,不需要重写任何方法。
对象反序列化流:ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
- 构造方法:ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
- 反序列化对象的方法:Object readObject():从ObjectInputStream读取一个对象
package com.testIO;import java.io.*;/*** @author 林高禄* @create 2020-05-10-13:11*/
public class ObjectInputStreamDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test//src//com//testIO//oos.txt"));Object obj = ois.readObject();Student s = (Student)obj;System.out.println(s.getName()+","+s.getAge());ois.close();}
}
输出:
林高禄,27
到这里,说明我们的反序列化成功
下面我们做一下骚修改,反序列化之前,我们对Student类做了些修改,比如重写了toString()方法
package com.testIO;import java.io.Serializable;/*** @author 林高禄* @create 2020-05-12-21:39*/
public class Student implements Serializable {private String name;private int age;public Student() {}public Student(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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
再执行一次反序列化Demo,控制台报以下异常
Exception in thread "main" java.io.InvalidClassException: com.testIO.Student; local class incompatible: stream classdesc serialVersionUID = 5613672065288821876, local class serialVersionUID = 7003572463648716337
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.testIO.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:12)
InvalidClassException:
当序列化运行时检测到类中的以下问题之一时抛出
- 类的串行版本与从流中读取的类描述符的类型不匹配
- 该类包含未知的数据类型
- 该类没有可访问的无惨构造函数
stream classdesc serialVersionUID = 5613672065288821876, local class serialVersionUID = 7003572463648716337
从这里我们知道,我们序列化是学生类的serialVersionUID = 5613672065288821876,而修改类后,local class serialVersionUID = 7003572463648716337,所以反序列异常
serialVersionUID
序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID,它在反序列化的过程中使用,以验证序列化对象的发送者和接收者是否加载了与序列化兼容的对象的类。如果接收者已经具有与对应发件人类别不用的serialVersionUID的对象加载了一个类,则反序列化将导致一个InvalidClassException。一个可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式地声明它自己的serialVersionUID,该字段必须是static,final,和long类型。
知道原因之后,我们又修改了学生类,声明serialVersionUID
package com.testIO;import java.io.Serializable;/*** @author 林高禄* @create 2020-05-12-21:39*/
public class Student implements Serializable {private static final long serialVersionUID = 22L;private String name;private int age;private transient int bb;public Student() {}public Student(String name, int age, int bb) {this.name = name;this.age = age;this.bb = bb;}public static Long getSerialVersionUID() {return serialVersionUID;}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 getBb() {return bb;}public void setBb(int bb) {this.bb = bb;}
}
package com.testIO;import java.io.*;/*** @author 林高禄* @create 2020-05-10-13:11*/
public class ObjectOutputStreamDemo {public static void main(String[] args) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test//src//com//testIO//oos.txt"));Student s = new Student("林高禄",27,55);oos.writeObject(s);oos.close();}
}
执行序列化Demo之后,在修改Student类的代码,比如重写toString()方法,再执行反序列化Demo
package com.testIO;import java.io.Serializable;/*** @author 林高禄* @create 2020-05-12-21:39*/
public class Student implements Serializable {private static final long serialVersionUID = 22L;private String name;private int age;private transient int bb;public Student() {}public Student(String name, int age, int bb) {this.name = name;this.age = age;this.bb = bb;}public static Long getSerialVersionUID() {return serialVersionUID;}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 getBb() {return bb;}public void setBb(int bb) {this.bb = bb;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", bb=" + bb +'}';}
}
package com.testIO;import java.io.*;/*** @author 林高禄* @create 2020-05-10-13:11*/
public class ObjectInputStreamDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test//src//com//testIO//oos.txt"));Object obj = ois.readObject();Student s = (Student)obj;System.out.println(s.getName()+","+s.getAge()+","+s.getBb());ois.close();}
}
输出:
林高禄,27,0
反序列化成功,但是我们发现bb=0,这是为什么呢,注意看学生类属性bb的定义, private transient int bb,关键字transient 作用就是使得修饰的属性不被序列化,所以反序列得出来的值是默认值0。
对象序列化流与对象反序列化流(ObjectOutputStream,ObjectInputStream)相关推荐
- java byte序列化,java对象序列化byte[] and byte[]反序列化对象--转
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOExceptio ...
- Java对象序列化文件追加对象的问题,以及Java的读取多个对象的问题解决方法。
Java对象序列化文件追加对象的问题,以及Java的读取多个对象的问题解决方法. 参考文章: (1)Java对象序列化文件追加对象的问题,以及Java的读取多个对象的问题解决方法. (2)https: ...
- java对象序列化克隆_JAVA 对象克隆和序列化
先用一个例子来说明假克隆吧,也就是用"="之后的效果.. [运行结果]: [运行结果] 姓名:rollen年龄:20 姓名:hello world年龄:100 姓名:hello w ...
- python在读写文件之前需要创建文件对象-Python对象序列化写入文件对象
1.创建Python文件对象的读写模式(r,w模式)与创建Java输入输出流: FileInputStream inputStream=new FileInputStream(new File(&qu ...
- Java对象序列化乱码6_对象序列化成字符串乱码解决
问题描述: 将一个对象序列化成字符串后,字符串是乱码的,并且反序列化报错. 代码如下: import com.alibaba.fastjson.JSONObject; import org.sprin ...
- 【java基础,IO合集】文件流、高级流(缓冲流、对象流)、 序列化接口java.io.Serrializable
目录 文件流 1 块读写的文件复制操作 2 文件输出流-覆盖模式 3 文件输出流-追加模式 4 文件输出流-读取文本数据 高级流 1 流连接示意图 2 缓冲流 2.1 使用缓冲流完成文件复制操作 2 ...
- Java基础(28)数据输入输出流、内存操作流、打印流、随机访问流、序列化与反序列化流、Properties类(集合)
1. 数据输入输出流 1. 数据输入输出流的概述: (1)以Stream结尾的,一般都是字节流 (2)数据输入流(DataInputStream):数据输入流允许应用程序以与机器无关方式从底层输入流中 ...
- java IO之 序列流 集合对象Properties 打印流 流对象
序列流 也称为合并流. SequenceInputStream 序列流,对多个流进行合并. SequenceInputStream 表示其他输入流的逻辑串联.它从输入流的有序集合开始,并从 第一个输入 ...
- java 对象怎么序列化,java对象序列化总结
java对象序列化小结 百度百科上介绍序列化是这样的: 序列化 (Serialization): 将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储 ...
- Java I/O中的对象序列化
Java I/O中的对象序列化 Java对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够以后将这个字节序列完全恢复为原来的对象.利用对象的序列化,可以实现轻量级持久性 ...
最新文章
- JVM内存调优原则及几种JVM内存调优方法
- 主席树 + 后缀数组求LCP + 二分套二分 ---- P4094 [HEOI2016/TJOI2016]字符串
- python中对象和变量的关系_浅析python中的类变量和对象变量
- 深度网络的设计与可视化工具
- 生产订单的 lock 与 unlock
- oracle 12c 新特性之不可见字段
- spring5高级编程_Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- Golang入门(4):并发
- set.seed(7)什么意思
- 【从线性回归到BP神经网络】第三部分:Logistic回归
- 微信公众号模板消息推送
- 快去抢票!今天开始!2020元旦春节火车票购票日程攻略来了
- 210_Python+OpenCV_04_模糊(均值、中值、高斯)
- 广东未来科技|民族科技助力立体显示终端产业集群崛起
- 《Effective Modern C++》翻译--条款2: 理解auto自动类型推导
- 计算机主板设计方案,解决方案:计算机主板每个组件的详细图示
- 【Windows问题解决】 Win10无法打开Wlan,但是驱动正常的解决方案
- 购车指南首次买车必看系列之(一): 保险篇
- Linux---------安装以及基本语法知识
- 1.6 例子:CIFAR-10分类
热门文章
- 集群和分布式 区别和优点
- 中国文化惊艳里约狂欢节
- 1634: Happy Thanksgiving Day - A + B Problem
- python json转字符串保留中文
- 【前端 HTML+CSS+JavaScript(JS)】DOM练习-onkeydown键盘事件-用wasd移动图片的位置 带注释/总结
- 干扰网络信号的app_解决Wi-Fi无线信号干扰的方法
- word考试计算机试题及答案,2017职称计算机考试Word2003冲刺试题及答案(1)
- word中怎么给公式+编号排版
- MBIST DFT测试概念
- DBSCAN原理及实现