对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息。 对象信息一旦写到文件上那么对象的信息就可以做到持久化了
  对象的输出流: 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;

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


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

原创:https://www.cnblogs.com/fnz0/p/5410856.html

Java——IO流 对象的序列化和反序列化流ObjectOutputStream和ObjectInputStream的更多相关文章

  1. Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream

    ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化. ObjectOutputStream 和 ObjectInputStream ...

  2. Java—IO流 对象的序列化和反序列化

    序列化的基本操作 1.对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化. 2.序列化流(ObjectOutputStream),writeObject 方法用于将对象写入输出流中 ...

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

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

  4. 类的序列化和反序列化(ObjectOutputStream和ObjectInputStream)

    1.需要序列化的类 import java.io.Serializable; /** * 必须继承 Serializable 接口才能实现序列化 */ public class Employee im ...

  5. ObjectOutputStream和ObjectInputStream对对象进行序列化和反序列化

    1 Java序列化和反序列化简介 Java序列化是指把对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为java对象的过程. 我们把对象序列化成有序字节流,保存到本地磁盘或者Redis等 ...

  6. Java对象的序列化与反序列化

    序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是 ...

  7. 【Java IO流】对象的序列化和反序列化

    对象的序列化和反序列化 1)对象序列化,就是将Object对象转换成byte序列,反之叫对象的反序列化. 2)序列化流(ObjectOutputStream),是字节的过滤流—— writeObjec ...

  8. Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream)

    Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.对象的序 ...

  9. Java IO(Properties/对象序列化/打印流/commons-io)

    Java IO(Properties/对象序列化/打印流/commons-io) Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载. ...

随机推荐

  1. padding填充属性

    内边距属性: 设置元素的内容与边框之间的距离. 分4个方向(上右下左): padding-top padding-right padding-bottom padding-left 说明:值不能为负值 ...

  2. 20155219付颖卓《网络对抗》EXP7网络欺诈技术防范

    实验后回答问题 1.通常在什么场景下容易受到DNS spoof攻击 在公共共享网络里,并且同一网段可以ping通的网络非常容易被攻击. 2.在日常生活工作中如何防范以上两攻击方法 不在不信任的公开网络 ...

  3. SQLI DUMB SERIES-16

    (1)无论怎么输入,都没有回显,但当输入 admin")#时,显示登录成功.若通过其他方法获取数据库的用户名,可通过这个方法登录成功. (2)获取其他信息可用考虑时间延迟注入.方法同15.

  4. app内嵌vue h5,安卓和ios拦截H5点击事件

    安卓和ios拦截h5点击事件,这个函数事件必须是暴漏在window下的 安卓和ios拦截普通h5函数: <div onclick = "show(),window.android.sh ...

  5. js date 和 math

    Math 用于执行常用的数学任务 console.log(Math.E); 自然数底数2.718 console.log(Math.PI); 圆周率3.1415926 console.log(Math ...

  6. ROS * 了解xacro的编写

    在urdf文件中,会有很多内容是一样的,当要改变这些语句重某一个相同的参数时却要更改很多次,很吗发,于是有了一种精简化.可复用.模块化的描述形式——xacro 废话少说 声明重复使用的常量 <? ...

  7. 巡风配置安装 –centOS6.5

    巡风是一款适用于企业内网的漏洞快速应急.巡航扫描系统,通过搜索功能可清晰的了解内部网络资产分布情况,并且可指定漏洞插件对搜索结果进行快速漏洞检测并输出结果报表. 其主体分为两部分:网络资产识别引擎,漏 ...

  8. day1||python

    测试题: 0. Python 是什么类型的语言? Python是一种面向对象.解释型.动态类型计算机程序设计语言解释型:程序无需编译成二进制代码,而是在执行时对语句一条一条编译动态类型:在程序执行过程 ...

  9. Python3 多线程例子

    import threading, zipfile class AsyncZip(threading.Thread): def __init__(self, infile, outfile): thr ...

  10. EasyMall注册功能

    EasyMall注册功能 1. 环境搭建 创建一个EasyMall的web应用 配置www.easymall.com网站,并配置为缺省的虚拟主机,将EasyMall配 置为缺省的web应用,在配置in ...