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

使用:

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

1、将User类的对象序列化

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

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

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

 public class Demo1 {

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

运行代码得到的结果:

账号:酒香逢 密码:123
OK

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

 class User implements Serializable{//必须实现Serializable接口
String uid;
String pwd;
String userName="名字";//新添加的成员变量
public User(String _uid,String _pwd){
this.uid = _uid;
this.pwd = _pwd;
}
@Override
public String toString() {
return "账号:"+this.uid+" 密码:"+this.pwd;
}
}

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

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

 class User implements Serializable{//必须实现Serializable接口

     private static final long serialVersionUID = 1L;
String uid;
String pwd;
//String userName="名字";//新添加的成员变量
public User(String _uid,String _pwd){
this.uid = _uid;
this.pwd = _pwd;
}
@Override
public String toString() {
return "账号:"+this.uid+" 密码:"+this.pwd;
}
}

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

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

 class Address implements Serializable{
String country;
String city;
} class User implements Serializable{//必须实现Serializable接口 private static final long serialVersionUID = 1L;
String uid;
String pwd;
String userName="名字";//新添加的成员变量
Address address;//成员变量为Address
public User(String _uid,String _pwd){
this.uid = _uid;
this.pwd = _pwd;
}
@Override
public String toString() {
return "账号:"+this.uid+" 密码:"+this.pwd;
}
}

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

 class User implements Serializable{//必须实现Serializable接口

     private static final long serialVersionUID = 1L;
String uid;
String pwd;
transient String userName="名字";//新添加的成员变量//添加关键字transient后,序列化时忽略
Address address;//成员变量为Address
public User(String _uid,String _pwd){
this.uid = _uid;
this.pwd = _pwd;
}
@Override
public String toString() {
return "账号:"+this.uid+" 密码:"+this.pwd;
}
}

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

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接口。

(JAVA)从零开始之--对象输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)的更多相关文章

  1. 对象输入输出流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. java 对象输入输出流

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

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

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

  7. 详解Java中的IO输入输出流!

    目录 本片要点 基本分类 发展史 文件字符流 输出的基本结构 流中的异常处理 异常处理新方式 读取的基本结构 运用输入与输出完成复制效果 文件字节流 缓冲流 字符缓冲流 装饰设计模式 转换流(适配器) ...

  8. JAVA之I/O 输入输出流详解

    简    介 如何在Java中进行文件的读写,Java IO流是必备的知识.这篇博文主要为您带来Java中的输入输出流的内容,包括文件编码.使用File类对文件和目录进行管理.字节流和字符流的基本操作 ...

  9. Java修炼——文件字节输入输出流复制和缓冲流复制

    一:文件字节输入输出流复制 首先明确数据源和目的文件,然后就是"中转站",最后就是关闭 package com.bjsxt.ioproject; import java.io.Fi ...

随机推荐

  1. TFS 2012使用简介(一)

    最近,一直想让团队加入敏捷开发,但TFS2010用下来,并不是令人满意,还好,TFS2012横空出世了.相比TFS2010,TFS2012改进太多了,主要体现在以下方面: Team Web Acces ...

  2. SQL Server阻止了对组件xp_cmdshell过程的解决方案

    使用SQL tools连接sqlserver时候出现以下问题: SQL Server阻止了对组件xp_cmdshell过程的解决方案错误描述:SQL Server阻止了对组件‘xp_cmdshell’ ...

  3. jquery 使用方式记录

    1.监听键盘事件 $("#id").keyup(function(event){ if(event.keyCode == 13){ $("#btn_addgoods_su ...

  4. Android WebRTC 音视频开发总结

    www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...

  5. 大众点评网王宏:从.Net迁移向Java平台 - 51CTO.COM

    大众点评网王宏:从.Net迁移向Java平台 - 51CTO.COM 大众点评网王宏:从.Net迁移向Java平台

  6. linux —— 搭建网页项目笔记

    导读 本文笔记之用,记录在我在linux下搭建与开发网站时遇到的一些碎片知识,以备将来之需. 目录 数据库相关 1.数据库相关 1) ubuntu 16.04 LTS 下mysql 的安装与使用  安 ...

  7. 一个Hibernate小程序

    基本步骤 在前一篇博文Hibernate环境搭建中为大家详细的介绍如何搭建一个学习新类库的学习环境.今天,为大家带来一个Hibernate小例子,让大家能够快速上手. 步骤如下: 1.配置hibern ...

  8. Partition算法剖析

    博文链接:http://haoyuanliu.github.io/2016/12/18/Partition%E7%AE%97%E6%B3%95%E5%89%96%E6%9E%90/ 对,我是来骗访问量 ...

  9. Hadoop最基本的wordcount(统计词频)

    package com.uniclick.dapa.dstest; import java.io.IOException; import java.net.URI; import org.apache ...

  10. Unit Test单元测试时如何模拟HttpContext

    参考文章:http://blog.csdn.net/bclz_vs/article/details/6902638 http://www.cnblogs.com/PurpleTide/archive/ ...