Java序列化与反序列化(实践)
Java序列化和反序列化相关应用技术及实例
(3)为什么要提供序列化 由于对象的寿命常随着生成该对象的程序的终止而终 止。 有时候可能需要将对象的状态保存下来,在需要时再 将对象恢复(精确的副本)以延续其状态; 也可能需要将对象从一个应用程序域发送到另一个应 用程序域中。
2、序列化的形式 (1)二进制序列化保持类型保真度 这对于在应用程序的不同调用之间保留对象的状态很 有用。 例如,通过将对象序列化到剪贴板,可在不同的应用 程序之间共享对象;也可以将对象序列化到流、磁盘、 内存和网络等等
Java序列化和反序列化 相关应用技术及实例
对象的序列化和反序列化技术
在本讲中您能了解如下知识点 对象的序列化技术 对象的反序列化技术 序列化的主要技术特点 相关的API 类与接口 对象的序列化应用实例
1、对象的序列化技术 (1)对象流:所谓的对象流也就是将对象的内容进行流化
可以对流化后的对象(如文件IO流)进行读写操作,也可将
5、在什么应用场合下考虑采用对象序列化的技术 (1)该类的对象是否需要跨应用程序域发送? (2)该类是否将与远程处理一起使用? (3)是否需要在另一种环境中实现对象的再生? (4)是否需要对对象的状态加以延续—-对象的持久化 6、序列化的主要技术特点 (1)如果某个类能够被序列化,其子类也可以被序列化。 (2)声明为static和transient类型的成员数据不能被序列 化 因为static代表类的状态,transient代表对象的临时数据。
(2)XML 序列化仅序列化公共属性和方法而不转换私有成 员变量,且不保留类型保真度 当希望提供或使用数据而不限制使用该数据的应用程 序时,这很有用 由于 XML 是一个开放式标准,因此在WebService技术 中的SOAP协议则是该应用 3、序列化分为两大部分:序列化和反序列化 (1)序列化 就是将数据分解成字节流(包括对象类型和版本等头 信息),以便存储在文件中或在网络上传输。 (2)反序列化 就是打开字节流并重构对象(JVM用头信息生成对象 实例,然后将对象字节流中的数据复制到对象数据成员 中)。
Hessian序列化和反序列化实现
Hessian序列化和反序列化实现先聊聊 Java的序列化,Java官⽅的序列化和反序列化的实现被太多⼈吐槽,这得归于Java官⽅序列化实现的⽅式。
1、Java序列化的性能经常被吐槽。
2、Java官⽅的序列化后的数据相对于⼀些优秀的序列化的⼯具,还是要⼤不少,⽐如probuf,这⼤⼤影响存储和传输的效率。
3、Java序列化⼀定需要实现Serializable接⼝4、Java序列化的 serialVersionUID 也是个⼤坑另外,序列化和反序列化中还需要考虑:跨语⾔,新旧对象版本兼容,安全,性能。
今天主要来说说,Hessian2是如何来解决这些问题的?⼀、跨语⾔:hessian提供了⼀整套的byte[]的写⼊规范,这个规范为其他的语⾔实现hessian的序列化和反序列化提供了可能。
/doc/hessian-serialization.html⽬前hessian2已经⽀持了⾮常多语⾔,Java,Node,php,Erlang,c#.......⼆、新旧对象版本兼容:hessian2将类的描述信息写⼊byte[]中,以便于在反序列化时候能正常。
但是这样就带来了⼀个问题:序列化后的内容较⼤。
三、安全,hessian序列化时,会调⽤writeReplace⽅法得到⼀个新的对象,能将对象中的⼀些值进⾏加密后在进⾏序列化。
四、性能:hessian2的序列化在内容的序列化上做了⼀些优化,hessian2将需要序列化的多个相同的对象只会写⼊⼀次,其他⽤到该对象的只使⽤对象的引⽤,⽽不重新写⼊对象的描述信息和值信息。
但是hessian2在描述信息上写⼊的信息来兼容动态化的反序列化⽀持,所以内容相对于⼀些描述性的序列化⼯具(thrift,protobuf)来说,在性能上没有优势。
再回到序列化,相对于 Java来说,hessian的序列化从跨语⾔,新旧对象的版本兼容,安全以及性能⽅⾯都做的好,主要体现在:⼀、Java的序列化⽆法跨语⾔。
Java中的序列化与反序列化技巧详解
Java中的序列化与反序列化技巧详解序列化与反序列化是Java中非常重要的概念和技术。
它们可以将对象转换为字节流,以便在网络上传输或者保存到文件中。
在本文中,我们将详细探讨Java中的序列化与反序列化技巧,包括如何实现序列化和反序列化,如何处理版本兼容性问题以及一些常见的注意事项。
一、序列化和反序列化的基本概念1. 序列化:将对象转换为字节流的过程称为序列化。
序列化后的字节流可以被保存到文件中或者通过网络传输。
2. 反序列化:将字节流转换为对象的过程称为反序列化。
反序列化可以从文件中读取字节流或者从网络中接收字节流。
3. Serializable接口:Java中的序列化和反序列化是通过Serializable接口实现的。
如果一个类实现了Serializable接口,那么它的对象可以被序列化和反序列化。
二、如何实现序列化和反序列化1. 实现Serializable接口:要使一个类可以被序列化,只需要让该类实现Serializable接口即可。
Serializable接口是一个标记接口,没有任何方法需要实现。
2. ObjectOutputStream和ObjectInputStream:Java提供了ObjectOutputStream和ObjectInputStream两个类来实现序列化和反序列化。
可以使用这两个类的writeObject()和readObject()方法来进行序列化和反序列化。
3. 序列化和反序列化的示例代码:```java// 序列化try {FileOutputStream fileOut = new FileOutputStream("object.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(object);out.close();fileOut.close();System.out.println("Serialized data is saved in object.ser");} catch (IOException i) {i.printStackTrace();}// 反序列化try {FileInputStream fileIn = new FileInputStream("object.ser");ObjectInputStream in = new ObjectInputStream(fileIn);Object object = (Object) in.readObject();in.close();fileIn.close();System.out.println("Deserialized data is loaded from object.ser"); } catch (IOException i) {i.printStackTrace();} catch (ClassNotFoundException c) {c.printStackTrace();}```三、版本兼容性问题的处理在进行序列化和反序列化时,可能会遇到版本兼容性的问题。
java对象的序列化以及反序列化详解
java对象的序列化以及反序列化详解⼀、概念序列化:把创建出来的对象(new出来的对象),以及对象中的成员变量的数据转化为字节数据,写到流中,然后存储到硬盘的⽂件中。
反序列化:可以把序列化后的对象(硬盘上的⽂件中的对象数据),读取到内存中,然后就可以直接使⽤对象。
这样做的好处是不⽤再⼀次创建对象了,直接反序列化就可以了。
使⽤场景:在创建对象并给所创建的对象赋予了值后,当前创建出来的对象是存放在堆内存中的,当JVM停⽌后,堆中的对象也被释放了,如果下⼀次想要继续使⽤之前的对象,需要再次创建对象并赋值。
然⽽使⽤序列化对象,就可以把创建出来的对象及对象中数据存放到硬盘的⽂件中,下次使⽤的时候不⽤在重新赋值,⽽是直接读取使⽤即可。
对象直接转换为字节的形式进⾏⽹络传输⼆、相关API介绍序列化序列化对象所属的类是ObjectOutputStream,如下图所⽰:说明:ObjectOutputStream类可以把对象及其数据写⼊到流中或⽹络中。
构造函数如下图所⽰:写出功能:反序列化反序列化对象所属的类是ObjectInputStream类:说明:序列化输出流对象和反序列化输出流对象都不具备读写能⼒,分别依赖FileOutputStream和FileInputStream类来进⾏读写⽂件。
构造函数如下图所⽰:读取功能:三、实战序列化需求:把Student类创建的对象持久化保存。
分析和步骤:1)⾃定义⼀个Student类,并定义name和age属性;2)定义⼀个测试类,在这个测试类中创建Student类的对象s;3)创建序列化对象objectOutputStream,同时创建输出流并关联硬盘上的⽂件;4)使⽤序列化对象objectOutputStream调⽤writeObject()函数持久化保存学⽣对象s;5)释放序列化对象流的资源;Student类如下:需要实现序列化接⼝Serializable,它是⼀个标记性接⼝。
Java对象序列化与反序列化过程详解
Java对象序列化与反序列化过程详解
在Java编程中,对象序列化(Serialization)和反序列化(Deserialization)是非常重要的概念。
对象序列化是将对象转换为字节流的过程,可以将对象存储到文件中、通过网络传输对象等。
反序列化则是将字节流转换回对象的过程。
本文将详细介绍Java对象序列化与反序列化的整个过程。
1. Java对象序列化
对象序列化是将Java对象转换为字节流的过程,可以使用ObjectOutputStream类来实现。
序列化一个对象的主要步骤如下:
•创建一个FileOutputStream或ByteArrayOutputStream对象,用于将字节写入文件或内存中。
•创建一个ObjectOutputStream对象,并将其与文件输出流或字节数组输出流连接。
•调用ObjectOutputStream对象的writeObject()方法,将对象序列化为字节流。
```java // 创建文件输出流 FileOutputStream fileOut = new FileOutputStream(。
JAVA基础4---序列化和反序列化深入整理(Hessian序列化)
JAVA基础4---序列化和反序列化深⼊整理(Hessian序列化)⼀、Hessian序列化⽤法1、maven依赖<dependency><groupId>com.caucho</groupId><artifactId>hessian</artifactId><version>4.0.38</version></dependency>2、序列化和反序列化1/** Hessian序列化 */2public static byte[] hessianSerialize(Object object){3 Hessian2Output oo = null;4byte[] result = null;5try {6 ByteArrayOutputStream bos = new ByteArrayOutputStream();7oo = new Hessian2Output(bos);8 oo.writeObject(object);9 oo.flush();10 result = bos.toByteArray();11 } catch (IOException e) {12 e.printStackTrace();13 }14return result;15 }1617/** Hessian反序列化 */18public static Object hessianSerializeToObj(byte[] bytes){19 Object result = null;20try{21 ByteArrayInputStream is = new ByteArrayInputStream(bytes);22Hessian2Input input = new Hessian2Input(is);23result = input.readObject();24 }catch (Exception e){25 e.printStackTrace();26 }27return result;28 }Hessian的序列化和反序列化分别是依靠Hessian2Output和Hessian2Input来实现,⾸先是定义⼀个⼆进制字节流对象ByteArrayOutputStream和ByteArrayOutputStream对象,分别通过对应的Hessian对象进⾏⼆进制流的读写操作。
java 对象 序列化 反序列化 方法
java 对象序列化反序列化方法Java 对象的序列化和反序列化是指将对象转换为字节流,以便于存储或传输,然后再将字节流转换回对象的过程。
在 Java 中,可以使用Serializable 接口和ObjectInputStream、ObjectOutputStream 类来实现对象的序列化和反序列化。
一、对象序列化对象序列化是将对象转换为字节流的过程。
在 Java 中,要实现对象序列化,需要满足以下两个条件:1. 类必须实现 Serializable 接口:Serializable 接口是一个标记接口,没有任何方法。
通过实现 Serializable 接口,表明该类的对象可以被序列化。
2. 字段必须是可序列化的:如果一个类的字段是对象类型,那么该对象的类也必须实现 Serializable 接口才能被序列化。
实现对象序列化的步骤如下:1. 创建一个类,实现 Serializable 接口。
2. 在类中定义字段,用于存储对象的属性。
3. 在类中提供构造方法和访问方法。
4. 使用 ObjectOutputStream 类将对象序列化为字节流。
下面是一个示例代码,演示了如何实现对象序列化:```javaimport java.io.Serializable;public class Student implements Serializable { private String name;private int age;public Student(String name, int age) { = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}}import java.io.FileOutputStream;import java.io.ObjectOutputStream;public class SerializationDemo {public static void main(String[] args) {Student student = new Student("John", 20);try {FileOutputStream fileOut = new FileOutputStream("student.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(student);out.close();fileOut.close();System.out.println("Serialized data is saved in student.ser");} catch (Exception e) {e.printStackTrace();}}}```在上述示例代码中,我们定义了一个Student 类,并实现了Serializable 接口。
Java实验报告--序列化
实验报告一. 实验名称JAVA序列化及反序列化二. 实验目的及要求1)熟练使用对象的序列化编写相应应用程序三. 实验环境Eclipse IDE四. 实验内容(1)学生成绩及成绩保存到本地磁盘“save.txt”中。
(2)学生的身份证号禁止序列化。
(3)运行时如果不存在“save.txt”,则重新录入学生的信息与成绩。
(4)如果存在“save.txt”,则显示学生信息与成绩。
五.实验过程及实验结果(1)创建学生类package student;import java io Serializable;public class Student implements Serializableprivate String id;private String name;private transient String card;private Double java;private Double sql;private Double jsp;public Studentpublic Student String id String name String card Double java Double sql Double jspthis id = id;this name = name;this card = card;this java = java;this sql = sql;this jsp = jsp;public String getIdreturn id;public void setId String idthis id = id;public String getNamereturn name;public void setName String namethis name = name;public String getCardreturn card;public void setCard String cardthis card = card;public Double getJavareturn java;public void setJava Double javathis java = java;public Double getSqlreturn sql;public void setSql Double sqlthis sql = sql;public Double getJspreturn jsp;public void setJsp Double jspthis jsp = jsp;@Overridepublic String toStringreturn "Student{" +"id='" + id + '\'' +", name='" + name + '\'' +", card='" + card + '\'' +", java=" + java +", sql=" + sql +", jsp=" + jsp +'}';public Double sumreturn java + sql + jsp;(2)创建测试类package student;import java.io.*;import java.util.Scanner;public class Demo {public static void main(String[] args) {try {File file = new File("./序列化/src/student/save.txt");if (file exists()) {ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));Student student = (Student) ois readObject();System out println("×××学生基本信息×××");System out println("编号姓名身份证");StringBuilder sb = new StringBuilder();sb append(student getId())append("")append(student getName())append(" ")append(student getCard()); System out println(sb);System out println();System out println("×××学生成绩×××");System out println("科目成绩");System out println("Java " + student getJava());System out println("Sql " + student getSql());System out println("Jsp " + student getJsp());System out println("总成绩 " + student sum());} else {Student st;Scanner sc = new Scanner(System in);String id name card;double java sql jsp;System out println("********输入学生信息********");System out print("学生编号:");id = sc next();System out print("学生姓名:");name = sc next();System out print("学生身份证:");card = sc next();System out print("Java成绩:");java = sc nextDouble();System out print("Sql成绩:");sql = sc nextDouble();System out print("Jsp成绩:");jsp = sc nextDouble();st = new Student(id name card java sql jsp);FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos);oos writeObject(st);fos close();oos close();System out println("信息已保存!");}} catch (Exception e) {System out println("保存失败!请重新运行程序!");e printStackTrace();}}}(3)测试截图六. 实验小结• 1. 当父类继承Serializable接口时,所有子类都可以被序列化。
Java序列化与反序列化面试题解析
Java序列化与反序列化面试题解析Java序列化与反序列化是面试中常见的话题之一。
理解和掌握这两个概念对于处理Java对象的持久化和网络传输等场景非常重要。
在本文中,我们将深入探讨Java序列化与反序列化,解析相关面试题,帮助您更好地理解和应对这个重要的话题。
一、什么是Java序列化与反序列化Java序列化指的是将Java对象转换为字节流的过程,以便在网络上传输或者存储到磁盘上。
相应地,反序列化是将字节流还原为Java对象的过程,从而实现对象的持久化或者网络传输。
二、为什么需要Java序列化与反序列化1. 对象持久化:Java序列化允许我们将一个对象的状态保存下来,并在需要的时候将其恢复,实现对象的持久化。
通过序列化和反序列化,我们可以将对象保存到磁盘上,或者在网络传输中进行数据交换。
2. 分布式计算:在网络分布式计算中,不同的计算节点之间需要进行对象的传输。
通过Java序列化与反序列化,我们可以方便地在不同的计算节点之间传输对象,提高分布式计算的效率。
3. 远程调用:在远程调用中,客户端和服务端之间需要传输Java对象。
通过序列化和反序列化,我们可以将Java对象转换为字节流,在网络上传输,并在服务端进行反序列化,从而实现远程方法调用。
三、Java序列化与反序列化的实现方式在Java中,我们可以使用Java序列化API实现对象的序列化与反序列化。
Java序列化API是Java.io包中的一组类,主要包括ObjectOutputStream和ObjectInputStream两个类。
1. 序列化:要实现Java对象的序列化,需要将对象的类实现Serializable接口。
在实现类中,可以通过写入ObjectOutputStream对象来将对象序列化为字节流。
例如:```javapublic class Employee implements Serializable {private String name;private int age;// ... 省略其他成员变量和方法}Employee employee = new Employee();// 设置对象的成员变量employee.setName("John");employee.setAge(30);// 将对象序列化为字节流try {FileOutputStream fileOut = new FileOutputStream("employee.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut);out.writeObject(employee);out.close();fileOut.close();} catch (IOException e) {e.printStackTrace();}```2. 反序列化:要实现Java对象的反序列化,需要使用ObjectInputStream对象从字节流中读取对象。
java 对象 序列化 反序列化 方法
java 对象序列化反序列化方法Java中的对象序列化和反序列化是指将Java对象转化为字节序列的过程,以及将字节序列转化为Java对象的过程。
序列化可以将对象的状态保存到磁盘文件或通过网络传输,而反序列化则可以将保存的状态重新恢复为对象。
在Java中,序列化和反序列化是通过实现Serializable接口来实现的。
Serializable接口是一个标记接口,没有任何方法。
当一个类实现了Serializable接口,就表示该类的对象可以被序列化和反序列化。
要实现对象的序列化,只需要在类的定义中添加implements Serializable,如下所示:```javapublic class MyClass implements Serializable {// 类的定义}```接下来,就可以使用Java提供的ObjectOutputStream类将对象序列化为字节序列。
ObjectOutputStream类提供了writeObject()方法用于将对象写入输出流,如下所示:```javaMyClass obj = new MyClass();ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("obj.ser"));out.writeObject(obj);out.close();```在上述代码中,首先创建一个MyClass的对象obj,然后创建一个ObjectOutputStream对象out,并将其与文件输出流相连。
最后调用out的writeObject()方法将obj对象写入输出流,并关闭输出流。
要实现对象的反序列化,需要使用Java提供的ObjectInputStream类。
ObjectInputStream类提供了readObject()方法用于从输入流中读取字节序列并将其反序列化为对象,如下所示:```javaObjectInputStream in = new ObjectInputStream(new FileInputStream("obj.ser"));MyClass obj = (MyClass) in.readObject();in.close();```在上述代码中,首先创建一个ObjectInputStream对象in,并将其与文件输入流相连。
Java面试题详解Java中的序列化和反序列化
Java面试题详解Java中的序列化和反序列化Java中的序列化和反序列化序列化和反序列化是Java中重要的概念,用于实现对象的持久化和数据传输。
本文将详细解析Java中的序列化和反序列化的概念、使用方法以及相关注意事项。
一、序列化和反序列化的概念1. 序列化序列化是指将Java对象转换为字节流的过程,以便在网络传输或存储到文件中。
序列化使得对象能够被传输和保存,也可以在不同的平台和语言间进行通信和数据交换。
2. 反序列化反序列化是指将字节流转换为Java对象的过程。
反序列化是序列化的逆过程,通过反序列化可以将保存在文件或通过网络传输的字节流重新转化为Java对象。
二、Java中的序列化和反序列化实现方式Java中提供了两种主要的序列化和反序列化的实现方式:Serializable和Externalizable接口,并且默认的序列化机制是基于Serializable接口的。
1. Serializable接口Serializable接口是Java中的一个标记接口,实现该接口的类可以通过默认的序列化机制进行序列化和反序列化。
需要注意的是,实现Serializable接口的类的所有成员变量都将被序列化,包括私有成员变量。
2. Externalizable接口Externalizable接口继承自Serializable接口,是一个自定义序列化和反序列化机制的接口。
实现Externalizable接口的类必须实现writeExternal和readExternal两个方法,用于控制对象的序列化和反序列化过程。
相对于Serializable接口,Externalizable接口提供了更大的灵活性和性能上的优势。
三、序列化和反序列化的应用与注意事项1. 序列化的应用序列化主要应用于以下场景:- 对象的持久化:将对象保存到文件,以便在程序下次运行时恢复对象的状态。
- 远程方法调用:客户端和服务器之间传递Java对象。
java对象序列化与对象反序列化
java对象序列化与对象反序列化Java对象序列化与对象反序列化是Java中比较重要的一个技术,可以帮助开发者对Java对象进行持久化存储、传输以及分布式调用,保证Java程序的可靠性和安全性。
本文将从概念、原理、用途和实现方面介绍Java对象序列化与对象反序列化。
一、概念Java对象序列化是指将Java对象转换为二进制流的过程,可以用于将对象保存在硬盘或者网络传输。
序列化后的对象包含Java对象的数据和类信息,可以在反序列化后还原为原来的对象,对Java对象进行快速和方便的持久化存储和传输。
Java对象反序列化是指将序列化的二进制数据流还原为Java对象的过程。
在反序列化过程中,Java虚拟机通过读取序列化数据流,重建对象的状态和类信息。
反序列化后的对象可以直接使用,不需要重新编写或者初始化数据和类信息。
二、原理Java对象序列化与对象反序列化都是通过Java IO流实现的。
在序列化过程中,将Java对象的数据和类信息通过序列化流转换为字节流,可以用于保存到硬盘或传输。
在反序列化过程中,通过反序列化流读取序列化的字节流,反解析还原为Java对象。
Java对象序列化过程中,将Java对象的数据和类信息转换为二进制流,并将其传输到远程对象或存储到本地;反序列化过程中,将序列化的二进制流转换为Java对象,并还原对象的状态和类信息。
序列化和反序列化过程中需要考虑Java对象的类加载机制、安全性和性能等因素。
三、用途Java对象序列化和对象反序列化可以用于多种场景,如:1. 分布式计算中,用于远程方法调用(RMI)或远程(EJB)对象调用;2. 对象数据持久化,将Java对象保存到硬盘或数据库中,实现数据的持久化存储和读取;3. 网络数据传输,将Java对象通过网络传输,实现数据的跨机通信;4. 序列化数据缓存,将Java对象序列化后保存到缓存中,提高访问速度和性能。
Java对象序列化和对象反序列化广泛应用于面向对象的软件开发,保证Java程序的可靠性和安全性,并且使得Java程序具有良好的可扩展性和互操作性。
Java序列化与反序列化对象的持久化存储
Java序列化与反序列化对象的持久化存储在Java开发中,对象的持久化存储是一个非常重要的概念。
序列化和反序列化是实现对象持久化存储的两个过程。
本文将详细介绍Java序列化与反序列化对象的持久化存储。
一、什么是Java序列化与反序列化在Java中,对象的序列化是指将对象转换为字节序列的过程。
而反序列化则是指将字节序列转换为对象的过程。
通过序列化和反序列化,可以将对象在网络中传输、在硬盘中存储等。
二、序列化的实现方式Java中提供了两种主要的序列化方式:实现Serializable接口和实现Externalizable接口。
1. 实现Serializable接口实现Serializable接口是实现Java对象序列化的常用方式。
只需要在类的定义中,添加implements Serializable语句,即可将该类的对象实例序列化和反序列化。
```javaimport java.io.Serializable;public class ExampleClass implements Serializable {private String name;private int age;// 省略getter和setter方法}```2. 实现Externalizable接口实现Externalizable接口是另一种实现Java对象序列化的方式,相比Serializable接口更加灵活,可以实现对序列化过程的精细控制。
```javaimport java.io.Externalizable;import java.io.IOException;import java.io.ObjectInput;import java.io.ObjectOutput;public class ExampleClass implements Externalizable {private String name;private int age;// 实现writeExternal和readExternal方法@Overridepublic void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name);out.writeInt(age);}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {name = (String) in.readObject();age = in.readInt();}// 省略getter和setter方法}```三、反序列化的实现方式进行反序列化操作时,需要使用Java的ObjectInputStream类和ObjectOutputStream类来读取和写入对象的字节序列。
Java对象操作流:序列化与反序列化
Java对象操作流:序列化与反序列化文章目录••oo▪▪▪oo▪▪oo▪▪▪▪▪o对象操作流1. 对象序列化流1.1.1 对象序列化介绍•对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象的机制。
•这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息。
•字节序列写到文件(或网络)之后,相当于文件中持久保存了一个对象的信息;反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。
1.1.2 对象序列化流: ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。
可以使用ObjectInputStream读取(重构)对象。
可以通过使用流的文件来实现对象的持久存储。
如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象构造方法:方法名说明ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream序列化对象的方法:方法名说明void writeObject(Object obj) 将指定的对象写入ObjectOutputStream 1.1.3 序列化示例代码注意事项:一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口(Serializable是一个标记接口,实现该接口,不需要重写任何方法)学生类:public class Student implements Serializable {private String name;private int age;public Student() {}public Student(String name, int age) { = name;this.age = age;}public String getName() {return name;}public void setName(String name) { = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}测试类class ObjectOutputStreamDemo {public static void main(String[] args) throws IOException {//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStreamObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("StreamFile\\oos.txt"));//创建对象Student s = new Student("赵丽颖", 18);//void writeObject(Object obj):将指定的对象写入ObjectOutputStreamoos.writeObject(s);//释放资源oos.close();}}2. 对象反序列化流2.1 对象反序列化流: ObjectInputStream•ObjectInputStream反序列化先前使用ObjectOutputStream 编写的原始数据和对象构造方法方法名说明ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream反序列化对象的方法方法名说明Object readObject() 从ObjectInputStream读取一个对象2.2 示例代码class ObjectInputStreamDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStreamObjectInputStream ois = new ObjectInputStream(new FileInputStream("StreamFile\\oos.txt"));//Object readObject():从ObjectInputStream读取一个对象Object obj = ois.readObject();Student s = (Student) obj;System.out.println(s.getName() + "," + s.getAge());ois.close();}}3. serialVersionUID&transient3.0 遇到的问题用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?首先进行序列化操作再将Bean对象中的private改为public反序列化会出问题,会抛出InvalidClassException异常原因分析仔细阅读错误,他说之前的serialVersionUID与现在的不匹配了这是因为Java虚拟机会判断如果我们自己没有定义,那么虚拟机会根据类中的信息会自动的计算出一个序列号。
java 序列化及反序列化
java 序列化及反序列化1.概念介绍序列化:将对象转化成流的过程称为序列化。
反序列化:将流转化成对象的过程称之为反序列化。
2.使用原则序列化与反序列化必须遵守的原则a)Java对象在java中要想使一个java对象可以实现序列化与反序列化,必须让该类实现java.io.Serializable接口从上述定义中可以看到该接口中未定义任何方法,这大大的简化了开发者b)序列化主要依赖java.io.ObjectOutputStream类,该类对java.io.FileOutputStream进一步做了封装,这里主要使用ObjectOutputStream类的writeObject()方法实现序列化功能。
3.Serializable接口应用通过下面的一段代码进行分析:package serialized;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.Date;public class SampleSerialize implements Serializable{ private int id;private String name;private boolean isboy;private Date birthday;/***@param id*@param name*@param isboy*@param birthday*/public SampleSerialize(int id, String name, boolean isboy, Date birthday) {super();this.id = id; = name;this.isboy = isboy;this.birthday = birthday;}/***@return the id*/public int getId() {return id;}/***@param id the id to set*/public void setId(int id) {this.id = id;}/***@return the name*/public String getName() {return name;}/***@param name the name to set*/public void setName(String name) { = name;}/***@return the isboy*/public boolean isIsboy() {return isboy;}/***@param isboy the isboy to set*/public void setIsboy(boolean isboy) {this.isboy = isboy;}/***@return the birthday*/public Date getBirthday() {return birthday;}/***@param birthday the birthday to set*/public void setBirthday(Date birthday) {this.birthday = birthday;}//输出public void printInfo() {System.out.println("id : " + this.id);System.out.println("name : " + );System.out.println("isboy : " + this.isboy);System.out.println("birthday : " + this.birthday);}public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("lib/data.dat"));ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("lib/data.dat"));SampleSerialize ss = new SampleSerialize(1,"Joary",true,newDate());SampleSerialize ss1 = new SampleSerialize(2,"坤",true,newDate());objOut.writeObject(ss);objOut.writeObject(ss1);SampleSerialize s = (SampleSerialize)objIn.readObject();s.printInfo();s = (SampleSerialize)objIn.readObject();s.printInfo();}}运行程序后,打开data文件,发现内容如下:每个文件都是以AC ED这个数字开始的,00 05代表对象序列化格式的版本号。
JAVA基础4---序列化和反序列化深入整理(JDK序列化)
JAVA基础4---序列化和反序列化深⼊整理(JDK序列化)⼀、什么是序列化和反序列化?序列化:将对象状态信息转化成可以存储或传输的形式的过程(Java中就是将对象转化成字节序列的过程)反序列化:从存储⽂件中恢复对象的过程(Java中就是通过字节序列转化成对象的过程)⼆、为什么要序列化和反序列化?Java中对象都是存储在内存中,准确地说是JVM的堆或栈内存中,可以各个线程之间进⾏对象传输,但是⽆法在进程之间进⾏传输。
另外如果需要在⽹络传输中传输对象也没有办法,同样内存中的对象也没有办法直接保存成⽂件。
所以需要对对象进⾏序列化,序列化对象之后⼀个个的Java对象就变成了字节序列,⽽字节序列是可以传输和存储的。
⽽反序列化就可以通过序列化⽣产的字节序列再恢复成序列化之前的对象状态及信息。
总结:1、进程之间传输对象(如RPC、RMI通信)2、⽹络通信时进⾏传输对象3、持久化对象时需要将对象序列化三、怎么序列化和反序列化?实现序列化的⽅式有很多种,常⽤的⽅式有如下⼏种:3.1、JDK序列化JDK序列化时JDK⾃带的序列化⽅式,使⽤其他也⽐较⽅便,只需要序列化的类实现了Serializable接⼝即可,Serializable接⼝没有定义任何⽅法和属性,所以只是起到了标识的作⽤,表⽰这个类是可以被序列化的。
如果没有实现Serializable接⼝⽽进⾏序列化操作就会抛出NotSerializableException异常。
能够序列化的字段:属性变量、⽗类的属性变量(⽗类也需要实现Serializablie接⼝)不能序列化的字段:静态变量、⽗类的属性变量、关键字transient修饰的变量、没有实现Serializable接⼝的对象属性3.1.1、Serializable接⼝案例定义类User、Person、Home、School分别如下1public class Home implements Serializable {2private String address;34public String getAddress() {5return address;6 }78public void setAddress(String address) {9this.address = address;10 }11 }1public class School {2private String schoolName;34public String getSchoolName() {5return schoolName;6 }78public void setSchoolName(String schoolName) {9this.schoolName = schoolName;10 }11 }1public class Person implements Serializable {23public static String parentType = "Person"; //⽗类静态变量45private String sex;//性别67public String getSex() {8return sex;9 }1011public void setSex(String sex) {12this.sex = sex;13 }14 }public class User extends Person implements Serializable {public static boolean alive; //静态变量private Long userId;//Long 类型private int age; //int 类型private String userName; //string 类型private String password; //string 类型private transient String IDCard; //不序列化的字段private Date birth; //Date类型private Home home; // 可以序列化的对象类型private School school; //不可以序列化的对象类型List<User> friends; //List类型/** set get ⽅法省略*/}案例中序列化的类为User,继承类Person,分别含有类Home和School的对象属性,序列化测试代码如下:1public class MainTest {2public static void main(String[] args) throws Exception{3 User user = new User();4 user.setAge(10);5 user.setBirth(new Date());6 user.setPassword("123456");7 user.setUserName("Jack");8 user.setUserId(100L);9 user.setSex("男");10 user.setIDCard("131313131313113");11 user.parentType = "son";//修改⽗类静态变量12 user.alive = true; //修改User类的静态变量1314 Home home = new Home();15 home.setAddress("中国浙江");16 School school = new School();17 school.setSchoolName("清华⼤学");18 user.setHome(home);//设置对象属性19// user.setSchool(school);//设置对象属性 (因为School类没有实现Seriliazable接⼝,所以如果设置就会报错)2021 List<User> friends = new ArrayList<User>();22 User userF = new User();23 userF.setUserId(101L);24 userF.setUserName("Friend");25 friends.add(userF);26 user.setFriends(friends);2728//序列化29 serializer(user);30//反序列化31 User newUser = derializer();32//验证33 System.out.println("验证两个对象是否相等");34 System.out.println("原对象地址:"+user.toString());35 System.out.println("新对象地址:"+newUser.toString());36 System.out.println("******************");37 System.out.println("打印两个对象");38 System.out.println("原对象数据:"+JSON.toJSON(user).toString());39 System.out.println("新对象数据:"+JSON.toJSON(newUser).toString());40 }4142/**序列化对象*/43private static void serializer(User user)throws Exception{44 ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("/Users/xxw/testlog/user.txt")));45 outputStream.writeObject(user);46 outputStream.close();47 }4849/**反序列化对象*/50private static User derializer()throws Exception{51 ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("/Users/xxw/testlog/user.txt")));52 User user = (User) inputStream.readObject();53 inputStream.close();54return user;55 }56 }测试结果为:1验证两个对象是否相等2原对象地址:er@3764951d3新对象地址:er@4783da3f4 ******************5打印两个对象6原对象数据:{"iDCard":"131313131313113","password":"123456","sex":"男","birth":1573203467764,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江" 7新对象数据:{"password":"123456","sex":"男","birth":1573203467764,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}}这⾥User类的School属性没有实现Serializable接⼝,所以如果给school属性赋值然后进⾏序列化就会报错,结果如下:1 Exception in thread "main" java.io.NotSerializableException: com.lucky.demo.base.seralizer.demo.School2 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)3 at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)4 at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)5 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)6 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)7 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)8 at com.lucky.demo.base.seralizer.demo.MainTest.serializer(MainTest.java:59)9 at com.lucky.demo.base.seralizer.demo.MainTest.main(MainTest.java:43)⽽如果User类的⽗类Person没有实现Serializable接⼝,那么序列化的时候不会报错,但是⽗类中的属性在反序列化之后字段就会没有,结果如下:1打印两个对象2原对象数据:{"iDCard":"131313131313113","password":"123456","sex":"男","birth":1573203839905,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江" 3新对象数据:{"password":"123456","birth":1573203839905,"userName":"Jack","userId":100,"age":10,"friends":[{"userName":"Friend","userId":101,"age":0}],"home":{"address":"中国浙江"}}这⾥就没有了⽗类的属性sex字段3.1.2、Serializable接⼝实现原理Serializable接⼝是⼀个空接⼝,没有定义任何的⽅法和属性,所以Serialiazable接⼝的作⽤就是起到⼀个标识的作⽤,源码如下1public interface Serializable {2 }Serializable接⼝既然是标识的作⽤,那么就需要在实际序列化操作的时候进⾏识别,⽽实际的序列化操作是通过ObjectOutputStream和ObjectInputStream实现的,那么接下来就看下这两个类的是如何实现序列化和反序列化的3.1.2.1、ObjectOutputStream源码解析构造函数如下1public ObjectOutputStream(OutputStream out) throws IOException {2 verifySubclass();3 bout = new BlockDataOutputStream(out);4 handles = new HandleTable(10, (float) 3.00);5 subs = new ReplaceTable(10, (float) 3.00);6 enableOverride = false;7 writeStreamHeader();8 bout.setBlockDataMode(true);9if (extendedDebugInfo) {10 debugInfoStack = new DebugTraceInfoStack();11 } else {12 debugInfoStack = null;13 }14 }OutoutStream表⽰保存的⼆进制流,也就是将序列化的对象保存到这个⼆进制流中,再看下具体的序列化⽅法源码如下:1public final void writeObject(Object obj) throws IOException {2if (enableOverride) {//enableOverride 表⽰是否可以被覆盖,默认为false3 writeObjectOverride(obj);4return;5 }6try {7//执⾏具体的序列化操作8writeObject0(obj, false);9 } catch (IOException ex) {10if (depth == 0) {11 writeFatalException(ex);12 }13throw ex;14 }15 }最终执⾏了writeObject0(obj, false)⽅法,代码如下:1private void writeObject0(Object obj, boolean unshared)2throws IOException3 {4boolean oldMode = bout.setBlockDataMode(false);5 depth++;6try {7// handle previously written and non-replaceable objects8// 处理已经处理过的和不可替换的对象,这些是不可序列化的9int h;10if ((obj = subs.lookup(obj)) == null) {11 writeNull();12return;13 } else if (!unshared && (h = handles.lookup(obj)) != -1) {14 writeHandle(h);15return;16 } else if (obj instanceof Class) {17 writeClass((Class) obj, unshared);18return;19 } else if (obj instanceof ObjectStreamClass) {20 writeClassDesc((ObjectStreamClass) obj, unshared);21return;22 }2324// check for replacement object25 Object orig = obj;26//获取对象的Class对象27 Class<?> cl = obj.getClass();28 ObjectStreamClass desc;29for (;;) {30// REMIND: skip this check for strings/arrays?31 Class<?> repCl;32//获取Class的描述信息,并且判断是否是Serializable接⼝33 desc = ObjectStreamClass.lookup(cl, true);34if (!desc.hasWriteReplaceMethod() ||35 (obj = desc.invokeWriteReplace(obj)) == null ||36 (repCl = obj.getClass()) == cl)37 {38break;39 }40 cl = repCl;41 }4243//如果允许被替换的情况44if (enableReplace) {45 Object rep = replaceObject(obj);46if (rep != obj && rep != null) {47 cl = rep.getClass();48 desc = ObjectStreamClass.lookup(cl, true);49 }50 obj = rep;51 }5253// if object replaced, run through original checks a second time54// 如果对象被替换了,只有是ObjectOutputStream的⼦类才会出现55if (obj != orig) {56 subs.assign(orig, obj);57if (obj == null) {58 writeNull();59return;60 } else if (!unshared && (h = handles.lookup(obj)) != -1) {61 writeHandle(h);62return;64 writeClass((Class) obj, unshared);65return;66 } else if (obj instanceof ObjectStreamClass) {67 writeClassDesc((ObjectStreamClass) obj, unshared);68return;69 }70 }7172// remaining cases73/**序列化不同类型的对象,分别序列化String、数组、枚举类型74 * 对于Integer、Long等都属于实现了Serializable接⼝的数据类型*/75 if (obj instanceof String) {//序列化字符串类型对象76 writeString((String) obj, unshared);77 } else if (cl.isArray()) {//序列化数组类型对象78 writeArray(obj, desc, unshared);79 } else if (obj instanceof Enum) {//序列化枚举类型对象80 writeEnum((Enum<?>) obj, desc, unshared);81 } else if (obj instanceof Serializable) {//序列化实现了Serializable接⼝的数据类型82 writeOrdinaryObject(obj, desc, unshared);83 } else {//抛出不可序列化异常84 if (extendedDebugInfo) {85 throw new NotSerializableException(86 cl.getName() + "\n" + debugInfoStack.toString());87 } else {88 throw new NotSerializableException(cl.getName());89 }90 }91 } finally {92 depth--;93 bout.setBlockDataMode(oldMode);94 }95 }96 }前⾯都是在做各种检查,实际有效的代码就是从75⾏开始,分别针对不同类型的对象分别执⾏不同的序列化⽅法writeString⽅法的逻辑就是将字符串按字节的⽅式进⾏序列化,底层就是通过数组复制的⽅式获取到char[],然后写⼊到缓存的序列化的byte[]数组中1 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);writeArray⽅法的逻辑就是先判断数组的数据类型是什么,如果是基本数据类型之间写⼊byte数字,如果是对象类型就调⽤writeObject0⽅法writeEnum⽅法的逻辑是直接写⼊枚举的值⽽对于对象类型是⽐较复杂的,也就是writeOrdinaryObject⽅法,逻辑如下:1private void writeOrdinaryObject(Object obj,2 ObjectStreamClass desc,3boolean unshared)4throws IOException5 {6if (extendedDebugInfo) {7 debugInfoStack.push(8 (depth == 1 ? "root " : "") + "object (class \"" +9 obj.getClass().getName() + "\", " + obj.toString() + ")");10 }11try {12//检查ObjectStreamClass对象13 desc.checkSerialize();1415//写⼊标记表⽰是Object类型16 bout.writeByte(TC_OBJECT);17//写⼊Class对象的描述信息18 writeClassDesc(desc, false);19 handles.assign(unshared ? null : obj);20if (desc.isExternalizable() && !desc.isProxy()) {21//写⼊实现了Externalizable接⼝的对象22 writeExternalData((Externalizable) obj);23 } else {24//写⼊实现了Serializable25 writeSerialData(obj, desc);26 }27 } finally {28if (extendedDebugInfo) {29 debugInfoStack.pop();30 }31 }32 }最终按实现了Externalizable接⼝或Serializable接⼝分别执⾏writeExternalData和writeSerialData⽅法,writeSerialData⽅法如下:1private void writeSerialData(Object obj, ObjectStreamClass desc)2throws IOException3 {4//获取类的描述信息对象5 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();6for (int i = 0; i < slots.length; i++) {7 ObjectStreamClass slotDesc = slots[i].desc;8//判断该类是否⾃定义类writeObject⽅法,如果重写了该⽅法则按重写的逻辑处理9if (slotDesc.hasWriteObjectMethod()) {10 ObjectOutputStream.PutFieldImpl oldPut = curPut;11 curPut = null;12 SerialCallbackContext oldContext = curContext;1314if (extendedDebugInfo) {15 debugInfoStack.push(16 "custom writeObject data (class \"" +17 slotDesc.getName() + "\")");18 }19try {20 curContext = new SerialCallbackContext(obj, slotDesc);21 bout.setBlockDataMode(true);22//通过反射的⽅式执⾏⾃定义的writeObejct⽅法23 slotDesc.invokeWriteObject(obj, this);24 bout.setBlockDataMode(false);25 bout.writeByte(TC_ENDBLOCKDATA);26 } finally {27 curContext.setUsed();28 curContext = oldContext;30 debugInfoStack.pop();31 }32 }3334 curPut = oldPut;35 } else {36//如果没有⾃定义writeObject⽅法则按默认的⽅法写⼊属性数据37 defaultWriteFields(obj, slotDesc);38 }39 }40 }先是根据类的描述信息判断是否⾃定义了序列化⽅法writeObejct⽅法,如果⾃定义了就通过反射执⾏invokeWriteObejct⽅法,如果没有⾃定义则执⾏defaultWriteFields⽅法,defaultWriteFields⽅法逻辑如下:1private void defaultWriteFields(Object obj, ObjectStreamClass desc)2throws IOException3 {4 Class<?> cl = desc.forClass();5//校验对象的类信息是否和类描述信息⼀致6if (cl != null && obj != null && !cl.isInstance(obj)) {7throw new ClassCastException();8 }910//11 desc.checkDefaultSerialize();1213int primDataSize = desc.getPrimDataSize();14if (primVals == null || primVals.length < primDataSize) {15 primVals = new byte[primDataSize];16 }17 desc.getPrimFieldValues(obj, primVals);18 bout.write(primVals, 0, primDataSize, false);1920 ObjectStreamField[] fields = desc.getFields(false);//获取所有属性21 Object[] objVals = new Object[desc.getNumObjFields()];//获取对象类型属性22int numPrimFields = fields.length - objVals.length;23 desc.getObjFieldValues(obj, objVals);24for (int i = 0; i < objVals.length; i++) {//遍历对象类型属性数组25if (extendedDebugInfo) {26 debugInfoStack.push(27 "field (class \"" + desc.getName() + "\", name: \"" +28 fields[numPrimFields + i].getName() + "\", type: \"" +29 fields[numPrimFields + i].getType() + "\")");30 }31try {32//递归写⼊对象类型的属性33 writeObject0(objVals[i],34 fields[numPrimFields + i].isUnshared());35 } finally {36if (extendedDebugInfo) {37 debugInfoStack.pop();38 }39 }40 }41 }总结:序列化的整体逻辑就是遍历对象的所有属性,递归执⾏序列化⽅法,直到序列化的对象是String、Array或者是Eunm类,则按String、Array、Enum的序列化⽅式写⼊字节流中。
java序列化与反序列化的实例详解
java序列化与反序列化的实例详解1.Java序列化与反序列化Java序列化是指把Java对象转换为字节序列的过程;⽽Java反序列化是指把字节序列恢复为Java对象的过程。
2.为什么需要序列化与反序列化我们知道,当两个进程进⾏远程通信时,可以相互发送各种类型的数据,包括⽂本、图⽚、⾳频、视频等,⽽这些数据都会以⼆进制序列的形式在⽹络上传送。
那么当两个Java进程进⾏通信时,能否实现进程间的对象传送呢?答案是可以的。
如何做到呢?这就需要Java序列化与反序列化了。
换句话说,⼀⽅⾯,发送⽅需要把这个Java对象转换为字节序列,然后在⽹络上传送;另⼀⽅⾯,接收⽅需要从字节序列中恢复出Java对象。
序列化简介Java 提供了⼀种对象序列化的机制,该机制中,⼀个对象可以被表⽰为⼀个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写⼊⽂件之后,可以从⽂件中读取出来,并且对它进⾏反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以⽤来在内存中新建对象。
整个过程都是 Java 虚拟机(JVM)独⽴的,也就是说,在⼀个平台上序列化的对象可以在另⼀个完全不同的平台上反序列化该对象。
类 ObjectInputStream 和 ObjectOutputStream 是⾼层次的数据流,它们包含序列化和反序列化对象的⽅法。
ObjectOutputStream 类包含很多写⽅法来写各种数据类型,但是⼀个特别的⽅法例外:publicfinalvoidwriteObject(Objectx)throwsIOException上⾯的⽅法序列化⼀个对象,并将它发送到输出流。
相似的 ObjectInputStream 类包含如下反序列化⼀个对象的⽅法:publicfinalObjectreadObject()throwsIOException, ClassNotFoundException该⽅法从流中取出⼀个对象,并将对象反序列化。
【Java】Java原生的序列化和反序列化
【Java】Java原⽣的序列化和反序列化写⼀个Java原⽣的序列化和反序列化的DEMO。
需序列化的类:package com.nicchagil.nativeserialize;import java.io.Serializable;public class User implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String userName;public User(Integer id, String userName) {super();this.id = id;erName = userName;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {erName = userName;}public static long getSerialversionuid() {return serialVersionUID;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());result = prime * result+ ((userName == null) ? 0 : userName.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;User other = (User) obj;if (id == null) {if (other.id != null)return false;} else if (!id.equals(other.id))return false;if (userName == null) {if (erName != null)return false;} else if (!userName.equals(erName))return false;return true;}@Overridepublic String toString() {return "User [id=" + id + ", userName=" + userName + "]";}}View Code⼯具类:package com.nicchagil.nativeserialize;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class NativeSerializeTools {/*** 序列化* @param filePath 序列化的路径* @param s 序列化的对象*/public static void write(String filePath, Serializable s) throws FileNotFoundException, IOException {if (filePath == null || filePath.length() == 0) {throw new RuntimeException("请传⼊序列化路径");}if (s == null) {throw new RuntimeException("请传⼊序列化对象");}File f = new File(filePath);ObjectOutputStream oos = null;FileOutputStream fos = null;try {fos = new FileOutputStream(f);oos = new ObjectOutputStream(fos);oos.writeObject(s);System.out.println("finish.");} finally {if (oos != null) {oos.close();}if (fos != null) {fos.close();}System.out.println("close the resource.");}}/*** 反序列化* @param filePath 反序列化的路径* @return反序列化的对象*/public static Object read(String filePath) throws ClassNotFoundException, FileNotFoundException, IOException { if (filePath == null || filePath.length() == 0) {throw new RuntimeException("请传⼊反序列化路径");}File f = new File(filePath);ObjectInputStream ois = null;FileInputStream fis = null;Object o = null;try {fis = new FileInputStream(f);ois = new ObjectInputStream(fis);o = ois.readObject();System.out.println("finish.");} finally {if (ois != null) {ois.close();}if (fis != null) {fis.close();}System.out.println("close the resource.");}return o;}}View Code测试类:package com.nicchagil.nativeserialize;import java.io.FileNotFoundException;import java.io.IOException;import org.junit.Assert;import org.junit.Test;public class HowToUse {private User user = new User(100, "Nick Huang");private String filePath = "d:/user.txt";@Testpublic void c1() throws FileNotFoundException, IOException {NativeSerializeTools.write(filePath, user);}@Testpublic void c2() throws FileNotFoundException, IOException, ClassNotFoundException { Object o = NativeSerializeTools.read(filePath);System.out.println(o);Assert.assertTrue(user.equals(o));}}View Code⽇志:finish.close the resource.finish.close the resource.User [id=100, userName=Nick Huang]View Code。
Java基础(五)-Java序列化与反序列化
Java基础(五)-Java序列化与反序列化本⽂主要从以下⽅⾯记录:1、Java序列化和反序列化是什么?2、为什么需要序列化与反序列化?3、怎么实现Java序列化和反序列化?4、⼏个序列化注意事项⼀、Java序列化和反序列化是什么? 通俗的来讲,序列化过程就是将对象转成⼆进制流存⼊内存或者⽂件,反序列化从内存或⽂件中读取⼆进制流转换成对象。
⼆、为什么需要序列化与反序列化? 其实这个问题也就是它们的应⽤场景有哪些?这样就容易回答多了。
⽐如⽂件(⽂本、图⽚等)进⾏传输,这些⽂件都是通过⼆进制序列的形式进⾏传输的(序列化过程),⽽接收⽅则要读取这些⼆进制数据进⾏相对应的转换(反序列化过程)。
除了这个它主要⽤于⽹络传输(进程之间的通信等)。
三、怎么实现Java序列化和反序列化? 要想实现序列化有个必要条件就是要实现Serializable接⼝或Externalizable接⼝。
⼤部分可能只知道有Serializable接⼝没有关注Externalizable接⼝,那么你看了本⽂之后就应该知道了,后⾯再介绍它们的区别。
有了上⾯个必要条件后还需要借助jdk中有两个类:java.io.ObjectOutputStream和java.io.ObjectInputStream,它们分别负责序列化和反序列化。
我们可以看下这两个类的说明就知道是这两个类负责相对应的功能。
/*** An ObjectOutputStream writes primitive data types and graphs of Java objects* to an OutputStream. The objects can be read (reconstituted) using an* ObjectInputStream. Persistent storage of objects can be accomplished by* using a file for the stream. If the stream is a network socket stream, the* objects can be reconstituted on another host or in another process.** <p>Only objects that support the java.io.Serializable interface can be* written to streams. The class of each serializable object is encoded* including the class name and signature of the class, the values of the* object's fields and arrays, and the closure of any other objects referenced* from the initial objects.* ...*/public class ObjectOutputStreamextends OutputStream implements ObjectOutput, ObjectStreamConstants{}/*** An ObjectInputStream deserializes primitive data and objects previously* written using an ObjectOutputStream.** <p>ObjectOutputStream and ObjectInputStream can provide an application with* persistent storage for graphs of objects when used with a FileOutputStream* and FileInputStream respectively. ObjectInputStream is used to recover* those objects previously serialized. Other uses include passing objects* between hosts using a socket stream or for marshaling and unmarshaling* arguments and parameters in a remote communication system.* ...*/public class ObjectInputStreamextends InputStream implements ObjectInput, ObjectStreamConstants{} 下⾯我们以学⽣对象为例,将对象序列化保存⾄⽂件中,再从⽂件中反序列化转换成对象。