对象的序列化和反序列化

来源:互联网 发布:日本机器人 知乎 编辑:程序博客网 时间:2024/06/06 01:23
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

22,ObjectInputStreamObjectOutputStream

22.1对象的序列化流和反序列化流

这两个流对象是用来操作对象的。

对象的序列化:就是让对象中封装的数据可以持久化存储。

对象的反序列化:就是通过存储的文件数据获取对象实体。

对象序列化的条件:

必须要实现Serializable接口,否则无法实现对象的序列化。此接口提供了一个serialVersionUID,用于验证序列化和反序列化时是否是同一个对象,如果不是则无法反列化。

ObjectInputStreamObjectOutputStream都是装饰类,用于增强流对象的功能。

其构造函数:

ObjectInputStream(InputStream out)

ObjectOutputStream(OutputStream out)

分别都接收一个字节流。

22.2对象的序列化

用到的流对象是:ObjectOutputStream 

使用其方法:writerObject(被序列化的对象);

多个对象,就多次调用writerObject().

注意:对象的序列化,只存储对象中非瞬态和非静态的字段。

如:

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.io.Serializable;public class ObjectOutputStream Demo {      public static void main(String[] args)throws FileNotFoundException, IOException {             //创建对象序列化流,将对象的数据保存在,指定的文件中。             ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:\\person.object"));             //序列化对象。             oos.writeObject(new Person("李四",44));             //关闭资源             oos.close();      }}class Person implements Serializable{//对象要序列化必须要实现此接口      private String name;     private int age;      public Person(String name,int age) {             super();             this.name = name;             this.age = age;      }      public String getName() {             return name;      }      public void setName(String name) {             this.name = name;      }      public int getAge() {             return age;      }      public void setAge(int age) {             this.age = age;      } }

22.3对象的反序列化

对象的反序列化使用流对象:ObjectInputStream

使用方法:readObject();此方法返回Object对象,需要进行强转。

多个对象被反序列化,就多次调用readObject()每次读取一个对象。

通过读取被序列化对象的文件,获取对象。

如:

import java.io.FileInputStream;import java.io.FileNotFoundException;importjava.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;importjava.io.ObjectOutputStream;import java.io.Serializable;public class ObjectOutputStream Demo {       public static void main(String[] args)throws ClassNotFoundException, FileNotFoundException, IOException {             //创建对象序列化流,将对象的数据保存在,指定的文件中。             ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:\\person.object"));             //反序列化对象。             Person p=(Person)ois.readObject();             System.out.println(p.getName()+"::"+p.getAge());             //关闭资源             ois.close();      }}/* *打印结果:李四::44 */


 

通过反序列化流,可以从一个存储对象数据的文件中获取这个对象,实现了对象数据的持久化存储和对象的获取。

注意:对象反序列化时要获取对象,必须要满足:

1,            有对象的序列化文件。

2,            要有对象所属的字节码文件。否则,无法获取对象。

 

 

如果一个对象被序列化后,其原有的数据被修改,这时就不能完成反序列化。

异常信息:

Exception in thread "main"java.io.InvalidClassException: IO.Person; local class incompatible: stream classdesc serialVersionUID = -5252691168862610579, local class serialVersionUID = -7585441751578431892

 

这是因为serialVersionUID号不一致造成的,对象的反序列化过程中,会检查这个版本号与原对象的版本号是否一致,如果不一致就无法完成反序化,serialVersionUID在类中如果没有明确声明的情况下,会根据类中的内容默认计算出一个,当然,也可在类中自己声明一个serialVersionUID,不管类中数据是否变化,只要此号不变,就可以完成反序列化。

如:

class Person implements Serializable{//对象要序列化必须要实现此接口      private static final long serialVersionUID = 1L;//显示声明serialVersionUID      private int age;      private String name;      public Person(String name,int age) {             super();             this.name = name;             this.age = age;      }      public String getName() {             return name;      }      public void setName(String name) {             this.name = name;      }      public int getAge() {             return age;      }      public void setAge(int age) {             this.age = age;      }}

22.4关键字transient(瞬态)

对象的序列化,其静态和非瞬态的字段是不能被存储到文件中的。

如果一个字段不是静态,但也不想被存储到文件中,就可以加上此关键字:transient

如:

import java.io.FileInputStream;import java.io.FileNotFoundException;importjava.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;importjava.io.ObjectOutputStream;import java.io.Serializable;public class ObjectOutputStreamDemo {      public static void main(String[] args)throws ClassNotFoundException, FileNotFoundException, IOException {             //创建对象序列化流,将对象的数据保存在,指定的文件中。             ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:\\person.object"));             //反序列化对象             Person p=(Person)ois.readObject();             System.out.println(p.getName()+"::"+p.getAge());             //关闭资源             ois.close();      }}class Personimplements Serializable{//对象要序列化必须要实现此接口      private static final long serialVersionUID = 1L;//显示声明serialVersionUID      private static int age;//静态属性      private transient String name;//瞬态属性      public Person(String name,int age) {             super();             this.name = name;             this.age = age;      }      public String getName() {             return name;      }      public void setName(String name) {             this.name = name;      }      public int getAge() {             return age;      }      public void setAge(int age) {             this.age = age;      }}/* *反序列化打印结果:null::0 */


 

注意:多个对象的序列化,就多次调用writeObject(),多个对象的反序列化就多次调用readObject(),有几个对象就读取几个。

import java.io.FileInputStream;import java.io.FileNotFoundException;importjava.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;importjava.io.ObjectOutputStream;import java.io.Serializable; public class ObjectOutputStream Demo {      public static void main(String[] args)throws ClassNotFoundException, FileNotFoundException, IOException {//           ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:\\person.object"));             //序列化多个对象//           oos.writeObject(new Person("李四",33));//           oos.writeObject(new Person("张三",24));//           oos.writeObject(new Person("小强",45));//           oos.writeObject(new Person("李明",23));//           oos.close();                          //创建对象序列化流,将对象的数据保存在,指定的文件中。             ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:\\person.object"));             //反序列化多个对象。             Person p1=(Person)ois.readObject();             Person p2=(Person)ois.readObject();             Person p3=(Person)ois.readObject();             Person p4=(Person)ois.readObject();             System.out.println(p1.getName()+"::"+p1.getAge());             System.out.println(p2.getName()+"::"+p2.getAge());             System.out.println(p3.getName()+"::"+p3.getAge());             System.out.println(p4.getName()+"::"+p4.getAge());             //关闭资源             ois.close();      }}class Person implements Serializable{//对象要序列化必须要实现此接口       private static final long serialVersionUID = 1L;//显示声明serialVersionUID      private int age;      private String name;      public Person(String name,int age) {             super();             this.name = name;             this.age = age;      }      public String getName() {             return name;      }      publicvoid setName(String name) {             this.name = name;      }      publicint getAge() {             return age;      }      publicvoid setAge(int age) {             this.age = age;      }} /* *打印结果:李四::33张三::24小强::45李明::23 */


 

总结:对象的序列化和反序列化可以将对象持久保存,并可以随时获取对象,实现了对象中数据的持久保存。对象要序列化必须要实现Serializable接口,并声明serialVersionUID号,以免反序列化时抛出异常。对象反序列化要获取对象,首先必须有保存对象的文件,其实,必须有对象所属的字节码文件。对象中的静态字段和transient修饰的字段是不能被序列化到文件中的。

 

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
原创粉丝点击