对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息。 对象信息一旦写到文件上那么对象的信息就可以做到持久化了   对象的输出流ObjectOutputStream   对象的输入流:  ObjectInputStream

使用:

对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程,对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。既然对象的输出流将对象写入到文件中称之为对象的序列化,那么可想而知对象所对应的class必须要实现Serializable接口。(查看源码可得知:Serializable接口没有任何的方法,只是作为一个标识接口存在)。

1、将User类的对象序列化

 1 class User implements Serializable{//必须实现Serializable接口
2 String uid;
3 String pwd;
4 public User(String _uid,String _pwd){
5 this.uid = _uid;
6 this.pwd = _pwd;
7 }
8 @Override
9 public String toString() {
10 return "账号:"+this.uid+" 密码:"+this.pwd;
11 }
12 }
13
14 public class Demo1 {
15
16 public static void main(String[] args) throws IOException {
17 //假设将对象信息写入到obj.txt文件中,事先已经在硬盘中建立了一个obj.txt文件
18 File f = new File("F:\\obj.txt");
19 writeObjec(f);
20 System.out.println("OK");
21 }
22
23 //定义方法把对象的信息写到硬盘上------>对象的序列化。
24 public static void writeObjec(File f) throws IOException{
25 FileOutputStream outputStream = new FileOutputStream(f);//创建文件字节输出流对象
26 ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
27 objectOutputStream.writeObject(new User("酒香逢","123"));
28 //最后记得关闭资源,objectOutputStream.close()内部已经将outputStream对象资源释放了,所以只需要关闭objectOutputStream即可
29 objectOutputStream.close();
30 }
31 }

运行程序得到记事本中存入的信息:可见已经序列化到记事本中

2、将序列化到记事本的内容反序列化

 1 public class Demo1 {
2
3 public static void main(String[] args) throws IOException, ClassNotFoundException {
4 //假设将对象信息写入到obj.txt文件中,事先已经在硬盘中建立了一个obj.txt文件
5 File f = new File("F:\\obj.txt");
6 //writeObjec(f);
7 readObject(f);
8 System.out.println("OK");
9 }
10
11 //定义方法把对象的信息写到硬盘上------>对象的序列化。
12 public static void writeObjec(File f) throws IOException{
13 FileOutputStream outputStream = new FileOutputStream(f);//创建文件字节输出流对象
14 ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
15 objectOutputStream.writeObject(new User("酒香逢","123"));
16 //最后记得关闭资源,objectOutputStream.close()内部已经将outputStream对象资源释放了,所以只需要关闭objectOutputStream即可
17 objectOutputStream.close();
18 }
19 //把文件中的对象信息读取出来-------->对象的反序列化
20 public static void readObject(File f) throws IOException, ClassNotFoundException{
21 FileInputStream inputStream = new FileInputStream(f);//创建文件字节输出流对象
22 ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
23 User user = (User)objectInputStream.readObject();
24 System.out.println(user);
25 }
26 }

运行代码得到的结果:

账号:酒香逢 密码:123 OK

但是,如果这时候这个obj.txt是我们项目中一个文件,而项目到后期在原来User类的基础上添加成员变量String userName;

 1 class User implements Serializable{//必须实现Serializable接口
2 String uid;
3 String pwd;
4 String userName="名字";//新添加的成员变量
5 public User(String _uid,String _pwd){
6 this.uid = _uid;
7 this.pwd = _pwd;
8 }
9 @Override
10 public String toString() {
11 return "账号:"+this.uid+" 密码:"+this.pwd;
12 }
13 }

这时候如果我们再反序列化,则会引发下面的异常:

Exception in thread "main" java.io.InvalidClassException: xuliehua.User; local class incompatible: stream classdesc serialVersionUID = 2161776237447595412, local class serialVersionUID = -3634244984882257127   at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)   at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)   at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)   at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)   at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)   at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)   at xuliehua.Demo1.readObject(Demo1.java:48)   at xuliehua.Demo1.main(Demo1.java:32)

异常信息解读:

serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是JVM(JAVA虚拟界)通过一个类的类名、成员、包名、工程名算出的一个数字。而这时候序列化文件中记录的serialVersionUID与项目中的不一致,即找不到对应的类来反序列化。

3、如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后 在序列化与反序列化的时候,jvm都不会再自己算这个 class的serialVersionUID了。

去掉刚才添加的成员变量userName;,并且在User类中指定一个serialVersionUID

 1 class User implements Serializable{//必须实现Serializable接口
2
3 private static final long serialVersionUID = 1L;
4 String uid;
5 String pwd;
6 //String userName="名字";//新添加的成员变量
7 public User(String _uid,String _pwd){
8 this.uid = _uid;
9 this.pwd = _pwd;
10 }
11 @Override
12 public String toString() {
13 return "账号:"+this.uid+" 密码:"+this.pwd;
14 }
15 }

重新序列化到obj.txt文件中,然后再类中再将userName添加回来(将上面User类中userName字段解注释),再一次执行反序列化操作,执行的结果跟之前反序列化的结果是一致的。可见这样解决后我们后期修改类也是可行的。

4、如果在User类中再添加成员变量,而这个变量为一个class ,如Address,那么Address类也必须要实现Serializable接口。

 1 class Address implements Serializable{
2 String country;
3 String city;
4 }
5
6 class User implements Serializable{//必须实现Serializable接口
7
8 private static final long serialVersionUID = 1L;
9 String uid;
10 String pwd;
11 String userName="名字";//新添加的成员变量
12 Address address;//成员变量为Address
13 public User(String _uid,String _pwd){
14 this.uid = _uid;
15 this.pwd = _pwd;
16 }
17 @Override
18 public String toString() {
19 return "账号:"+this.uid+" 密码:"+this.pwd;
20 }
21 }

5、最后再提一下关键字transient关键字,当你不想要某些字段序列化时候,可以用transient关键字修饰

 1 class User implements Serializable{//必须实现Serializable接口
2
3 private static final long serialVersionUID = 1L;
4 String uid;
5 String pwd;
6 transient String userName="名字";//新添加的成员变量//添加关键字transient后,序列化时忽略
7 Address address;//成员变量为Address
8 public User(String _uid,String _pwd){
9 this.uid = _uid;
10 this.pwd = _pwd;
11 }
12 @Override
13 public String toString() {
14 return "账号:"+this.uid+" 密码:"+this.pwd;
15 }
16 }

最后总结一下对象输入输出流使用时需要注意:

1. 如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。 Serializable接口没有任何的方法,是一个标识接口而已。 2. 对象的反序列化创建对象的时候并不会调用到构造方法的、(这点文中没有说到,想要验证的同学在构造方法后面加一句System.out.println("构造方法执行吗?");,实际上构造方法是不执行的,自然这句话也没有输出了) 3. serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出的一个数字。 4. 使用ObjectInputStream反序列化的时候,ObjeectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUID 进行对比,如果这两个id不一致,反序列则失败。 5. 如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后 在序列化与反序列化的时候,jvm都不会再自己算这个 class的serialVersionUID了。 6. 如果一个对象某个数据不想被序列化到硬盘上,可以使用关键字transient修饰。 7. 如果一个类维护了另外一个类的引用,则另外一个类也需要实现Serializable接口。

对象输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)的更多相关文章

  1. (JAVA)从零开始之--对象输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)

    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流:  Ob ...

  2. 对象输入输出流ObjectInputStream、ObjectOutputStream(对象的序列化与反序列化)

    如题 所有关联的类需要继承Serializable 接口 文件为空,直接反序列化为发生错误; 毕竟对象为null , 序列化到文件里不是空空的! 以下笔记的原文连接: https://www.cnbl ...

  3. 输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)

    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流:  Ob ...

  4. Day 18:SequenceInputStream、合并切割mp3、对象输入输出流对象

    SequenceInputStream用例题讲述用法 需求:1.把a.txt与b.txt 文件的内容合并 2.把a.txt与b.txt .c.txt文件的内容合并 import java.io.Fil ...

  5. serialVersionUID序列化版本号与ObjectOutputStream对象输入输出流

    1. 观察ObjectOutputStream 我们观察ObjectOutputStream就可以发现该类没有无参构造,只有有参构造,所以他是一个包装流 2. 具体使用: public static ...

  6. java 对象输入输出流

    对象的输入输出流的作用: 用于写入对象 的信息读取对象的信息. 对象的持久化. 比如:用户信息.              ObjectInputStream   : 对象输入流            ...

  7. (21)IO流之对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream

    当创建对象时,程序运行时它就会存在,但是程序停止时,对象也就消失了.但是如果希望对象在程序不运行的情况下仍能存在并保存其信息,将会非常有用,对象将被重建并且拥有与程序上次运行时拥有的信息相同.可以使用 ...

  8. Java——IO流 对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream

    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流:  Ob ...

  9. java 对象序列化与反序列化

    Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化  Java序列化是指把Java对象转换为 ...

随机推荐

  1. 2016/05/16 UEditor 文本编辑器 使用教程与使用方法

    第一:百度UEditor编辑器的官方下载地址 ueditor 官方地址:http://ueditor.baidu.com/website/index.html 开发文档地址:http://uedito ...

  2. Common non-standard response fields

    https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#cite_note-52 Common non-standard response f ...

  3. USACO26 moofest 奶牛集会(归并排序)

    听说这题也是bzoj的3378&&poj1990,然而没有权限号交不了..poj懒得登. 题意:有n个奶牛,他们相互发出max(a[i].v,a[j].v)*abs(a[i].p-a[ ...

  4. YTU 2953: A代码填充--学画画

    2953: A代码填充--学画画 时间限制: 1 Sec  内存限制: 128 MB 提交: 62  解决: 52 题目描述 最近小平迷上了画画,经过琨姐的指导,他学会了RGB色彩的混合方法.对于两种 ...

  5. Fresco-Facebook的图片加载框架的使用

    目前常用的开源图片加载框架有:1.Universal-Image-Loader,该项目存在于Github上面https://github.com/nostra13/Android-Universal- ...

  6. POJ - 1470 Closest Common Ancestors(离线Tarjan算法)

    1.输出测试用例中是最近公共祖先的节点,以及这个节点作为最近公共祖先的次数. 2.最近公共祖先,离线Tarjan算法 3. /* POJ 1470 给出一颗有向树,Q个查询 输出查询结果中每个点出现次 ...

  7. 将多个jar合并为一个jar

    有时候,我们需要将多个jar合并为一个jar,ant提供了这样的一个功能 build.xml文件如下 执行以上任务会将 当前目录下的 mysql.jar,commons-io.jar合并为一个 all ...

  8. 视图表单访问控制器操作方法的POST、GET方式对应关系

    在视图中,表单默认访问方式是FormMethod.Post(不会将请求显示在地址栏中).在控制器中,操作方法不标注属性,默认为HttpGet属性.会有以下情况出现. 1.表单不指定访问方式(默认形式为 ...

  9. 真正认识 realloc 的工作方式(转载)

    转自:http://www.cnblogs.com/ren54/archive/2008/11/20/1337545.html realloc 用过很多次了.无非就是将已经存在的一块内存扩大. cha ...

  10. python 高阶函数二 map()和reduce()

    一.map()函数 map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. >>> fro ...