Java对象的序列化和反序列化实践

合集下载

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用头信息生成对象 实例,然后将对象字节流中的数据复制到对象数据成员 中)。

java对象的序列化和反序列化

java对象的序列化和反序列化

java对象的序列化和反序列化本⽂实例为⼤家分享了java对象的序列化和反序列化,供⼤家参考,具体内容如下1. 什么是序列化将对象转换为字节流保存起来,⽐如保存到⽂件⾥,并在以后还原这个对象,这种机制叫做对象序列化。

(补充⼀句:把对象保存到永久存储设备上称为持久化)2. 怎么实现序列化需要实现Serializable接⼝,java对象实现了这个接⼝就表明这个这个类的对象是可序列化的。

3. 序列化的注意事项(1)当⼀个对象序列化时,只能保存对象的⾮静态成员变量,不能保存⽅法和静态成员变量。

(2)对象A引⽤了对象B,对象A序列化了,B也跟着序列化了。

(3)如果⼀个可序化对象包含了⼀个不可序列化对象的引⽤,那么整个序列化操作就会失败,失败就会抛NotSerializableException,所以,本⾝对象和引⽤对象都要实现Serializable接⼝才可以进⾏序列化。

(4) transient的使⽤,成员变量或者引⽤标记为transient,那么对象仍可序死化,只是不会被序列化到⽂件中。

4. 代码public class Person implements Serializable {private String name;private transient int age;public Person(String name, int age) {super(); = name;this.age = age;}public String toString() {return + "-" + this.age;}}public class SerializableClient {public static void main(String[] args) throws Exception {Person p1 = new Person("zhangsan", 5);Person p2 = new Person("lisi", 100);//序列化FileOutputStream fos = new FileOutputStream("person.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(p1);oos.writeObject(p2);System.out.println("---------");//反序列化FileInputStream fis = new FileInputStream("person.txt");ObjectInputStream ois = new ObjectInputStream(fis);for(int i = 0; i < 2; i++) {Person tempPerson = (Person)ois.readObject();System.out.println(tempPerson);}}}输出结果:---------zhangsan-0lisi-05. 更细粒度的控制序列化和反序化当我们在序列化或者反序列化的类中实现了以上两个private⽅法(⽅法声明要与上⾯的保持完全⼀致),那么就允许我们以更加底层、更加继粒度的⽅式控制序列化和反序列化的过程。

Java对象操作流:序列化与反序列化

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中的序列化和反序列化

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对象的序列化与反序列化-Json篇

Java对象的序列化与反序列化-Json篇

Java对象的序列化与反序列化-Json篇说到Java对象的序列化与反序列化,我们⾸先想到的应该是Java的Serializable接⼝,这玩意在两个系统之间的DTO对象⾥⾯可能会⽤到,⽤于系统之间的数据传输。

或者在RPC(远程⽅法调⽤)时可能会⽤到。

但其实若是⽤于数据传输,xml和json两种数据格式⽤得更多⼀些。

但是为什么不⽤XStream呢,XStream确实好⽤,但是在Applet环境下可以使⽤的xml类库也就只有jdom了,连dom4j在Applet环境下都没有权限使⽤(Java反射的某些特性是需要权限的,Applet的安全机制不允许)。

扯远了,本⽂要说的是Java对象与Json的相互转换。

⽬前Java常⽤的Json类库有3种,即fastjson、jackson和gson,分别介绍如何将⼀个Java对象转换成Json和将⼀个Json字符串转换成Java对象,其实它们的⽤法⼤同⼩异。

⼀、⾸先看Maven依赖⼆、需要序列化的POJO和初始化代码三、fastjson的使⽤四、jackson的使⽤五、gson的使⽤⼀、⾸先看Maven依赖若不会maven,请参考Maven的基本⽤法:1 <!-- json -->2 <!-- 引⼊fastjson依赖 -->3 <dependency>4 <groupId>com.alibaba</groupId>5 <artifactId>fastjson</artifactId>6 <version>1.2.12</version>7 </dependency>8 <!-- 引jackson依赖 -->9 <!-- jackson核⼼包,必选,提供基于“流模式”解析的API -->10 <dependency>11 <groupId>com.fasterxml.jackson.core</groupId>12 <artifactId>jackson-core</artifactId>13 <version>2.7.4</version>14 </dependency>15 <!-- jackson注解包,可选,提供注解功能 -->16 <dependency>17 <groupId>com.fasterxml.jackson.core</groupId>18 <artifactId>jackson-annotations</artifactId>19 <version>2.7.4</version>20 </dependency>21 <!-- jackson数据绑定包,可选,提供基于“对象绑定”和“树模型”相关API -->22 <dependency>23 <groupId>com.fasterxml.jackson.core</groupId>24 <artifactId>jackson-databind</artifactId>25 <version>2.7.4</version>26 </dependency>27 <!-- 引⼊gson依赖 -->28 <dependency>29 <groupId>com.google.code.gson</groupId>30 <artifactId>gson</artifactId>31 <version>2.6.2</version>32 </dependency>⼆、需要序列化的POJO和初始化代码以下3种类库的使⽤均使⽤下⾯这个POJO1public class User {2public User(){}3private String id;4private String name;5private String password;6public String getId() {7return id;8 }9public void setId(String id) {10this.id = id;11 }12public String getName() {13return name;14 }15public void setName(String name) { = name;17 }18public String getPassword() {19return password;20 }21public void setPassword(String password) {22this.password = password;23 }24 @Override25public String toString() {26return"User [id=" + id + ", name=" + name + ", password=" + password27 + "]";28 }29 }1/**2 * 初始化User对象3 * @return user4*/5private static User initUser(){6 User user = new User();7 user.setId("1");8 user.setName("jison");9 user.setPassword("jison");10return user;11 }三、fastjson的使⽤fastjson的主要⼯具类是JSON,以下代码实现Java对象的序列化与反序列化1// 将Java对象序列化为Json字符串2 String objectToJson = JSON.toJSONString(initUser());3 System.out.println(objectToJson);4// 将Json字符串反序列化为Java对象5 User user = JSON.parseObject(objectToJson, User.class);6 System.out.println(user);四、jackson的使⽤jackson我们经常⽤到的是它的数据绑定包下的ObjectMapper类,以下代码实现Java对象的序列化与反序列化ObjectMapper objectMapper = new ObjectMapper();// 将Java对象序列化为Json字符串String objectToJson = objectMapper.writeValueAsString(initUser());System.out.println(objectToJson);// 将Json字符串反序列化为Java对象User user = objectMapper.readValue(objectToJson, User.class);System.out.println(user);五、gson的使⽤gson的主要⼯具类是Gson,使⽤GsonBuilder构造,以下代码实现Java对象的序列化与反序列化1 Gson gson = new GsonBuilder().create();2// 将Java对象序列化为Json字符串3 String objectToJson = gson.toJson(initUser());4 System.out.println(objectToJson);5// 将Json字符串反序列化为Java对象6 User user = gson.fromJson(objectToJson, User.class);7 System.out.println(user);以上3种json类库的完整代码如下:1public class JsonUtils {23/**4 * 初始化User对象5 * @return user6*/7private static User initUser(){8 User user = new User();9 user.setId("1");10 user.setName("jison");11 user.setPassword("jison");12return user;13 }1415public static void main(String[] args) throws Exception {16// fastjson⽤法17 fastjson();18// jackson⽤法19 jackson();20// gson⽤法21 gson();22 }2324private static void fastjson(){25// 将Java对象序列化为Json字符串26 String objectToJson = JSON.toJSONString(initUser());27 System.out.println(objectToJson);28// 将Json字符串反序列化为Java对象29 User user = JSON.parseObject(objectToJson, User.class);30 System.out.println(user);31 }3233private static void jackson() throws Exception{34 ObjectMapper objectMapper = new ObjectMapper();35// 将Java对象序列化为Json字符串36 String objectToJson = objectMapper.writeValueAsString(initUser());37 System.out.println(objectToJson);38// 将Json字符串反序列化为Java对象39 User user = objectMapper.readValue(objectToJson, User.class);40 System.out.println(user);41 }4243private static void gson(){44 Gson gson = new GsonBuilder().create();45// 将Java对象序列化为Json字符串46 String objectToJson = gson.toJson(initUser());47 System.out.println(objectToJson);48// 将Json字符串反序列化为Java对象49 User user = gson.fromJson(objectToJson, User.class);50 System.out.println(user);51 }52 }。

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对象序列化与对象反序列化

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对象的序列化以及反序列化详解⼀、概念序列化:把创建出来的对象(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,它是⼀个标记性接⼝。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java对象的序列化和反序列化实践当两个进程在进行远程通信时,彼此可以发送各种类型的数据。

无论是何种类型的数据,都会以二进制序列的形式在网络上传送。

发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

把Java对象转换为字节序列的过程称为对象的序列化。

把字节序列恢复为Java对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;2)在网络上传送对象的字节序列。

一.JDK类库中的序列化APIjava.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

、只有实现了Serializable和Externalizable接口的类的对象才能被序列化。

Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。

对象序列化包括如下步骤:1)创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;2)通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:1)创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;2)通过对象输入流的readObject()方法读取对象。

下面让我们来看一个对应的例子,类的内容如下:import java.io.*;import java.util.Date;/*** 对象的序列化和反序列化测试类.* @author <a href="mailto:xiexingxing1121@">AmigoXie</a> * @version 1.0* Creation date: 2007-9-15 - 下午21:45:48*/public class ObjectSaver {/*** @param args* @author <a href="mailto:xiexingxing1121@">AmigoXie</a> * Creation date: 2007-9-15 - 下午21:45:37*/public static void main(String[] args) throws Exception { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:""objectFile.obj"));//序列化对象Customer customer = new Customer("阿蜜果", 24);out.writeObject("你好!");out.writeObject(new Date());out.writeObject(customer);out.writeInt(123); //写入基本类型数据out.close();//反序列化对象ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:""objectFile.obj"));System.out.println("obj1=" + (String) in.readObject());System.out.println("obj2=" + (Date) in.readObject());Customer obj3 = (Customer) in.readObject();System.out.println("obj3=" + obj3);int obj4 = in.readInt();System.out.println("obj4=" + obj4);in.close();}}class Customer implements Serializable {private String name;private int age;public Customer(String name, int age) { = name;this.age = age;}public String toString() {return "name=" + name + ", age=" + age;}}输出结果如下:obj1=你好!obj2=Sat Sep 15 22:02:21 CST 2007obj3=name=阿蜜果, age=24obj4=123因此例比较简单,在此不再详述。

二.实现Serializable接口ObjectOutputStream只能对Serializable接口的类的对象进行序列化。

默认情况下,ObjectOutputStream按照默认方式序列化,这种序列化方式仅仅对对象的非transient的实例变量进行序列化,而不会序列化对象的transient的实例变量,也不会序列化静态变量。

当ObjectOutputStream按照默认方式反序列化时,具有如下特点:1)如果在内存中对象所属的类还没有被加载,那么会先加载并初始化这个类。

如果在classpath中不存在相应的类文件,那么会抛出ClassNotFoundException;2)在反序列化时不会调用类的任何构造方法。

如果用户希望控制类的序列化方式,可以在可序列化类中提供以下形式的writeObject()和readObject()方法。

private void writeObject(java.io.ObjectOutputStream out) throws IOExceptionprivate void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException;当ObjectOutputStream对一个Customer对象进行序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法,否则就按默认方式序列化。

在该对象的writeObjectt()方法中,可以先调用ObjectOutputStream的defaultWriteObject()方法,使得对象输出流先执行默认的序列化操作。

同理可得出反序列化的情况,不过这次是defaultReadObject()方法。

有些对象中包含一些敏感信息,这些信息不宜对外公开。

如果按照默认方式对它们序列化,那么它们的序列化数据在网络上传输时,可能会被不法份子窃取。

对于这类信息,可以对它们进行加密后再序列化,在反序列化时则需要解密,再恢复为原来的信息。

默认的序列化方式会序列化整个对象图,这需要递归遍历对象图。

如果对象图很复杂,递归遍历操作需要消耗很多的空间和时间,它的内部数据结构为双向列表。

在应用时,如果对某些成员变量都改为transient类型,将节省空间和时间,提高序列化的性能。

三.实现Externalizable接口Externalizable接口继承自Serializable接口,如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为。

Externalizable接口声明了两个方法:public void writeExternal(ObjectOutput out) throws IOExceptionpublic void readExternal(ObjectInput in) throws IOException , ClassNotFoundException前者负责序列化操作,后者负责反序列化操作。

在对实现了Externalizable接口的类的对象进行反序列化时,会先调用类的不带参数的构造方法,这是有别于默认反序列方式的。

如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出java.io.InvalidException:no valid constructor异常。

四.可序列化类的不同版本的序列化兼容性凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:以上serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。

如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。

类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。

为了提高哦啊serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。

显式地定义serialVersionUID有两种用途:1)在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;2)在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

相关文档
最新文档