ObjectOutputStream 序列化流
对象的序列化:将内存中的对象通过输出流写入到硬盘上(存入文本文件)或者在网络中传输(通过内存流)
序列化的前提:必须实现Serializable接口(标记接口)的类对象,特别注意自定义的类
实现此接口的类:String、包装类、Date类等
实现此接口的目的:给对象一个标记(序列化版本号),防止篡改(盖个章)
补充:此流继承自OutputStream
开发步骤:
(1)创建ObjectOutputStream流对象--封装目的源
(2)通过输出流的writeObject()方法写对象
注意1:对应文件虽然保存了对象的序列化形式的数据,但是文件无法用普通的文本编辑器打开,只有ObjectInputStream流通过反序列化才能识别。
注意2:通常对象中的属性都会被序列化,但是对于一些敏感数据,比如银行卡密码之类的,一旦序列化,外界就可以通过读取文件或拦截网络传输数据的方式窃取这些信息,出于安全问题,应该禁止这种属性进行序列化,将敏感属性用transient关键字来修饰就不会再参与序列化和反序列化的过程。
自定义writeObject()中的内容
原因:当ObjectOutputStream对一个对象进行序列化时,如果该对象具有writeObject()方法就会执行这一方法,否则会按默认
方式序列化
--------------------------------------------------
ObjectInputStream:反序列化流
对象的反序列化:从硬盘中去通过输入流去读取对象,恢复成内存中的对象
开发步骤:
(1)创建ObjectInputStream流对象--封装数据源
(2)通过输入流的readObject()方法读对象,要强转成本身的类型
注意:为了能读取正确的数据,必须保证对象输出流写对象的顺序与从对象输出流读对象的顺序一致
readObject()方法在进行反序列化时特点:不必调用类的构造方法,就会在内存中创建一个新的对象,对象的属性值来自于对象的序列化数据。
说明:readObject()和writeObject()方法并不是在java.io.Serializable接口中定义的。如果用户希望进一步控制可序列化类的序列化方式,就可以实现这两个方法,并且这两个方法的签名必须和自定义类中的readObject()和writeObject()方法签名完全一致
简单的讲:一个可序列化类中加入readObject()和writeObject()方法,就能定制序列化的方式
方法签名:由方法名称和一个参数列表(方法的参数的顺序和类型)组成。注意:方法签名不包括方法的返回类型
思考:多个对象存储到文件中,想读特定的文件(将对象保存到容器中,然后写入到文件中,通过角标来读取特定的对象)
延伸:需求,如果敏感数据想传输怎么办?
(1)首先将敏感属性用transient修饰
(2)实现序列化接口的类自定义writeObject()和readObject()方法
原因:若类不仅实现了Serializable接口,还自定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则会采用以下方式进行序列化与反序列化:ObjectOutputStream调用writeObject()方法时会调用对象的writeObject(ObjectOutputStream out)方法进行序列化。ObjectInputStream会调用对象的readObject(ObjectInputStream in)的方法进行反序列化。
实例2
package serializable; import java.io.*; public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { Student student = new Student("月亮颂", "520wzj"); System.out.println("序列化前"+student); /** * 序列化的步骤---浪一下 * * (1)创建字节数组对象(内存操作流) * * (2)把对象数列化到一个字节缓存中,而不是硬盘中 * * (3)再从字节缓存中反序列化此对象 */ ByteArrayOutputStream buf = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(buf); //传统的方式:是FileOutputStream流对象关联到硬盘 oos.writeObject(student);//将此对象写入到内存中暂存 //从此字节缓冲中反序列化student对象 ByteArrayInputStream bis = new ByteArrayInputStream(buf.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); student = (Student) in.readObject(); System.out.println("序列化后"+student); } }
相关链接: 点击打开链接