java 序列化与反序列化的实例详解

所属分类: 软件编程 / java 阅读数: 23
收藏 0 赞 0 分享

 1.Java序列化与反序列化

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

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

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

 序列化简介

Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

ObjectInputStreamObjectOutputStream 是高层次的数据流,它们包含序列化和反序列化对象的方法。

ObjectOutputStream 类包含很多写方法来写各种数据类型,但是一个特别的方法例外:

publicfinalvoidwriteObject(Objectx)throwsIOException

上面的方法序列化一个对象,并将它发送到输出流。相似的 ObjectInputStream 类包含如下反序列化一个对象的方法:

publicfinalObjectreadObject()throwsIOException, ClassNotFoundException

该方法从流中取出一个对象,并将对象反序列化。它的返回值为Object,因此,你需要将它转换成合适的数据类型。
为了演示序列化在Java中是怎样工作的,我们定义Employee类,该类实现了Serializable 接口。

Employee.java 文件代码:

public class Employee implements java.io.Serializable 
{ 
  public String name; 
  public String address; 
  public transient int SSN; 
  public int number; 
  public void mailCheck() 
  { 
   System.out.println("Mailing a check to " + name 
              + " " + address); 
  } 
} 

注意,一个类的对象要想序列化成功,必须满足两个条件:

1、该类必须实现 java.io.Serializable 对象。

2、该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable接口。

序列化对象

ObjectOutputStream 类用来序列化一个对象,如下的 SerializeDemo 例子实例化了一个 Employee 对象,并将该对象序列化到一个文件中。

该程序执行后,就创建了一个名为 employee.ser 文件。该程序没有任何输出,但是你可以通过代码研读来理解程序的作用。

注意: 当序列化一个对象到文件时, 按照 Java 的标准约定是给文件一个 .ser 扩展名。

SerializeDemo.java 文件代码:

import java.io.*; 
  
public class SerializeDemo 
{ 
  public static void main(String [] args) 
  { 
   Employee e = new Employee(); 
   e.name = "Reyan Ali"; 
   e.address = "Phokka Kuan, Ambehta Peer"; 
   e.SSN = 11122333; 
   e.number = 101; 
   try 
   { 
     FileOutputStream fileOut = 
     new FileOutputStream("employee.ser"); 
     ObjectOutputStream out = new ObjectOutputStream(fileOut); 
     out.writeObject(e); 
     out.close(); 
     fileOut.close(); 
     System.out.println("Serialized data is saved in employee.ser"); 
   }catch(IOException i) 
   { 
     i.printStackTrace(); 
   } 
  } 
} 
 

反序列化对象

下面的 DeserializeDemo 程序实现了反序列化,employee.ser 存储了 Employee 对象。

DeserializeDemo.java 文件代码:

import java.io.*; 
public class DeserializeDemo  
{ 
    public static void main(String [] args) 
    { 
     Employee e = null; 
     try 
     { 
       FileInputStream fileIn = new FileInputStream("employee.ser"); 
       ObjectInputStream in = new ObjectInputStream(fileIn); 
       e = (Employee) in.readObject(); 
       in.close(); 
       fileIn.close(); 
     }catch(IOException i) 
     { 
       i.printStackTrace(); 
       return; 
     }catch(ClassNotFoundException c) 
     { 
       System.out.println("Employee class not found"); 
       c.printStackTrace(); 
       return; 
     } 
     System.out.println("Deserialized Employee..."); 
     System.out.println("Name: " + e.name); 
     System.out.println("Address: " + e.address); 
     System.out.println("SSN: " + e.SSN); 
     System.out.println("Number: " + e.number); 
    } 
} 
 

以上程序编译运行结果如下所示:

Deserialized Employee...
Name: Reyan Ali
Address: Phokka Kuan, Ambehta Peer
SSN: 0
Number: 101

这里要注意以下要点:

readObject() 方法中的 try/catch代码块尝试捕获 ClassNotFoundException 异常。对于 JVM 可以反序列化对象,它必须是能够找到字节码的类。如果JVM在反序列化对象的过程中找不到该类,则抛出一个 ClassNotFoundException 异常。

注意,readObject() 方法的返回值被转化成 Employee 引用。

当对象被序列化时,属性 SSN 的值为 111222333,但是因为该属性是短暂的,该值没有被发送到输出流。所以反序列化后 Employee 对象的 SSN 属性为 0。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多精彩内容其他人还在看

Java的面向对象编程基本概念学习笔记整理

这篇文章主要介绍了Java的面向对象编程基本概念学习笔记整理,包括类与方法以及多态等支持面向对象语言中的重要特点,需要的朋友可以参考下
收藏 0 赞 0 分享

Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法

这篇文章主要介绍了Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

基于Java实现杨辉三角 LeetCode Pascal's Triangle

这篇文章主要介绍了基于Java实现杨辉三角 LeetCode Pascal's Triangle的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中Spring获取bean方法小结

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?下面通过本文给大家介绍Java中Spring获取bean方法小结,对spring获取bean方法相关知识感兴趣的朋友一起学习吧
收藏 0 赞 0 分享

如何计算Java对象占用了多少空间?

在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小,需要的朋友可以参考下
收藏 0 赞 0 分享

剖析Java中的事件处理与异常处理机制

这篇文章主要介绍了Java中的事件处理与异常处理机制,讲解Java是如何对事件或者异常作出响应以及定义异常的一些方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Java的Struts2框架的结构及其数据转移方式

这篇文章主要介绍了详解Java的Struts2框架的结构及其数据转移方式,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

Java封装好的mail包发送电子邮件的类

本文给大家分享了2个java封装好的mail包发送电子邮件的类,并附上使用方法,小伙伴们可以根据自己的需求自由选择。
收藏 0 赞 0 分享

在Java的Struts中判断是否调用AJAX及用拦截器对其优化

这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

java多线程Future和Callable类示例分享

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。今天我们就来研究下Future和Callab
收藏 0 赞 0 分享
查看更多