Java序列化

来源:互联网 发布:新东方网络学校 编辑:程序博客网 时间:2024/05/21 07:46

序列化:将java对象转换为字节序列的过程叫做序列化

反序列化:将字节对象转换为java对象的过程叫做反序列化

通常情况下,序列化有两种用途:、

1) 把对象的字节序列永久的保存在硬盘中

2)在网络上传输对象的字节序列

只有实现了Serializable或者Externalizable接口的类的对象才能够被序列化。否则当调用writeObject方法的时候会出现IOException。

首先要明白,什么是序列化?
我们经常看到一个实体类实现Serializable接口,这种用法就是序列化。目的是保存对象的状态,以便将它读取出来。
序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。
序列化将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例
Java为我们提供一种比较好的保存对象状态的机制,那就是序列化。
也就是说,保存状态和读取状态的事java已经帮我们做了,我们只需调相应的方法就可以了。

序列化的什么特点:
如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。

其次要搞清楚,什么情况下需要实例化?
 1、当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
 2、当你想用套接字在网络上传送对象的时候;
 java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
 3、当你想通过RMI传输对象的时候;
 RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。


 最后,就是如何实现序列化的?
 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如:  
 Foo  myFoo = new Foo(); 
 myFoo .setWidth(37); 
 myFoo.setHeight(70); 
 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它 从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。
 FileOutputStream fs = new FileOutputStream("foo.ser");
 ObjectOutputStream os = new ObjectOutputStream(fs);
 os.writeObject(myBox);
 os.close();
 
 ObjectInputStream in = new ObjectInputStream (new FileInputStream("foo.ser"));
 Box box = (Box) (in.readObject());
 System.out.println(box.toString());
 System.out.println(box.height);
 in.close();


Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨。

 1.Java序列化与反序列化

 Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。

 2.为什么需要序列化与反序列化

 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。

 当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。

3.如何实现Java序列化与反序列化

1)JDK类库中序列化API

 java.io.ObjectOutputStream:表示对象输出流

它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream:表示对象输入流

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

2)实现序列化的要求

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常。

3)实现Java对象序列化与反序列化的方法

假定一个Student类,它的对象需要序列化,可以有如下三种方法:

方法一:若Student类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化

ObjectOutputStream采用默认的序列化方式,对Student对象的非transient的实例变量进行序列化。

ObjcetInputStream采用默认的反序列化方式,对对Student对象的非transient的实例变量进行反序列化。

方法二:若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。

ObjectOutputStream调用Student对象的writeObject(ObjectOutputStream out)的方法进行序列化。

ObjectInputStream会调用Student对象的readObject(ObjectInputStream in)的方法进行反序列化。

方法三:若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。

ObjectOutputStream调用Student对象的writeExternal(ObjectOutput out))的方法进行序列化。

ObjectInputStream会调用Student对象的readExternal(ObjectInput in)的方法进行反序列化。

4)JDK类库中序列化的步骤

步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:

ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));

步骤二:通过对象输出流的writeObject()方法写对象:

out.writeObject(“Hello”);

out.writeObject(new Date());

5)JDK类库中反序列化的步骤

步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:

ObjectInputStream in = new ObjectInputStream(new fileInputStream(“D:\\objectfile.obj”));

步骤二:通过对象输出流的readObject()方法读取对象:

String obj1 = (String)in.readObject();

Date obj2 = (Date)in.readObject();

说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

为了更好地理解Java序列化与反序列化,选择方法一编码实现。

Student类定义如下:

[java] view plaincopy
  1. package com.jieke.io;  
  2. import java.io.Serializable;  
  3.   
  4. /** 
  5.  *Title:学生类 
  6.  *Description:实现序列化接口的学生类 
  7.  *Copyright: copyright(c) 2012 
  8.  *Filename: Student.java 
  9.  *@author Wang Luqing 
  10.  *@version 1.0 
  11.  */  
  12. public class Student implements Serializable  
  13. {  
  14.  private String name;  
  15.  private char sex;  
  16.  private int year;  
  17.  private double gpa;  
  18.   
  19.  public Student()  
  20.  {  
  21.   
  22.  }  
  23.  public Student(String name,char sex,int year,double gpa)  
  24.  {  
  25.   this.name = name;  
  26.   this.sex = sex;  
  27.   this.year = year;  
  28.   this.gpa = gpa;  
  29.  }  
  30.   
  31.  public void setName(String name)  
  32.  {  
  33.   this.name = name;  
  34.  }  
  35.   
  36.  public void setSex(char sex)  
  37.  {  
  38.   this.sex = sex;  
  39.  }  
  40.   
  41.  public void setYear(int year)  
  42.  {  
  43.   this.year = year;  
  44.  }  
  45.   
  46.  public void setGpa(double gpa)  
  47.  {  
  48.   this.gpa = gpa;  
  49.  }  
  50.   
  51.  public String getName()  
  52.  {  
  53.   return this.name;  
  54.  }  
  55.    
  56.  public char getSex()  
  57.  {  
  58.   return this.sex;  
  59.  }  
  60.   
  61.  public int getYear()  
  62.  {  
  63.   return this.year;  
  64.  }  
  65.   
  66.  public double getGpa()  
  67.  {  
  68.   return this.gpa;  
  69.  }  
  70. }  

把Student类的对象序列化到文件O:\\Java\\com\\jieke\\io\\student.txt,并从该文件中反序列化,向console显示结果。代码如下:

[java] view plaincopy
  1. import java.io.*;  
  2.   
  3. /** 
  4.  *Title:应用学生类 
  5.  *Description:实现学生类实例的序列化与反序列化 
  6.  *Copyright: copyright(c) 2012 
  7.  *Filename: UseStudent.java 
  8.  *@author Wang Luqing 
  9.  *@version 1.0 
  10.  */  
  11.   
  12. public class UseStudent  
  13. {  
  14.  public static void main(String[] args)  
  15.  {  
  16.   Student st = new Student("Tom",'M',20,3.6);  
  17.   File file = new File("O:\\Java\\com\\jieke\\io\\student.txt");  
  18.   try  
  19.   {  
  20.    file.createNewFile();  
  21.   }  
  22.   catch(IOException e)  
  23.   {  
  24.    e.printStackTrace();  
  25.   }  
  26.   try  
  27.   {  
  28.    //Student对象序列化过程  
  29.    FileOutputStream fos = new FileOutputStream(file);  
  30.    ObjectOutputStream oos = new ObjectOutputStream(fos);  
  31.    oos.writeObject(st);  
  32.    oos.flush();  
  33.    oos.close();  
  34.    fos.close();  
  35.   
  36.    //Student对象反序列化过程  
  37.    FileInputStream fis = new FileInputStream(file);  
  38.    ObjectInputStream ois = new ObjectInputStream(fis);  
  39.    Student st1 = (Student) ois.readObject();  
  40.    System.out.println("name = " + st1.getName());  
  41.    System.out.println("sex = " + st1.getSex());  
  42.    System.out.println("year = " + st1.getYear());  
  43.    System.out.println("gpa = " + st1.getGpa());  
  44.    ois.close();  
  45.    fis.close();  
  46.   }  
  47.   catch(ClassNotFoundException e)  
  48.   {  
  49.    e.printStackTrace();  
  50.   }  
  51.   catch (IOException e)  
  52.   {  
  53.    e.printStackTrace();  
  54.   }               
  55.  }  
  56. }  

结果如下所示:

name = Tom

sex = M

year = 20

gpa = 3.6

总结:

1)Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。

2)采用Java序列化与反序列化技术,一是可以实现数据的持久化,在MVC模式中很是有用;二是可以对象数据的远程通信。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 一年级孩子数学理解能力差怎么办 小孩一年级数学学不好怎么办 孩子一年级数学学不好怎么办 小学一年级数学学不好怎么办 孩子一年级数学成绩不好怎么办 成绩差的孩子该怎么办 面对成绩差的孩子该怎么办 六年级数学成绩差该怎么办 孩子数学物理成绩差该怎么办 高三成绩很差该怎么办 孩子学习成绩差家长该怎么办 孩子一年级语文成绩不好怎么办 孩子上网成瘾不听父母话怎么办 10岁数学不开窍怎么办 孩子五年级数学不好怎么办 一岁宝宝难断奶怎么办 2岁宝宝断不了奶怎么办 快2岁宝宝不听话怎么办 2岁半的宝宝不听话怎么办 3岁宝宝哭闹不止怎么办 2岁宝宝爱打人怎么办 两周岁宝宝吃东西就吐怎么办 两周岁宝宝不爱吃饭怎么办 两周岁宝宝反复发烧怎么办 两周岁宝宝咳嗽厉害怎么办 2岁宝宝体内有火怎么办 4岁宝宝数都不会怎么办 两岁宝宝太撅怎么办 儿童晚上发烧白天不发烧怎么办 宝宝晚上睡觉认人怎么办 两岁宝宝尿裤子怎么办 分手了想和好怎么办说 2岁半宝宝胆小怎么办 1岁半宝宝胆小怎么办 分手了还是想他怎么办 两岁宝宝夜惊怎么办 孩子误吃了牙膏怎么办 孩子跳舞脸上的妆卸不掉怎么办 4周岁还不会说话怎么办 宝贝2岁多还不会说话怎么办 孩子20个月离婚怎么办