Java入门 - 高级教程 - 04.序列化

原文地址:http://www.work100.net/training/java-serialization.html
更多教程:光束云 - 免费课程

序列化

序号 文内章节 视频
1 概述 -
2 序列化对象 -
3 反序列化对象 -

请参照如上章节导航进行阅读

1.概述

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

将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。

整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

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

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

public final void writeObject(Object x) throws IOException

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

public final Object readObject() throws IOException,
                                 ClassNotFoundException

该方法从流中取出下一个对象,并将对象反序列化。它的返回值为 Object,因此,你需要将它转换成合适的数据类型。

为了演示序列化在 Java 中是怎样工作的,我将使用之前教程中提到的 Employee 类,假设我们定义了如下的 Employee 类,该类实现了 Serializable 接口。

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);
   }
}

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

该类必须实现 java.io.Serializable 接口。

该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable 接口。

2.序列化对象

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

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

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

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("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      }catch(IOException i)
      {
          i.printStackTrace();
      }
   }
}

3.反序列化对象

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

import java.io.*;

public class DeserializeDemo
{
   public static void main(String [] args)
   {
      Employee e = null;
      try
      {
         FileInputStream fileIn = new FileInputStream("/tmp/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



上一篇:泛型
下一篇:网络编程


如果对课程内容感兴趣,可以扫码关注我们的 公众号QQ群,及时关注我们的课程更新


原文地址:https://blog.51cto.com/14735583/2476241

时间: 2024-08-28 21:18:29

Java入门 - 高级教程 - 04.序列化的相关文章

Java入门 - 高级教程 - 03.泛型

原文地址:http://www.work100.net/training/java-generic.html 更多教程:光束云 - 免费课程 泛型 序号 文内章节 视频 1 概述 2 泛型方法 3 泛型类 4 类型通配符 请参照如上章节导航进行阅读 1.概述 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 假定我们有这样一个需求

Java入门 - 高级教程 - 09.文档注释

原文地址:http://www.work100.net/training/java-documentation.html更多教程:光束云 - 免费课程 文档注释 序号 文内章节 视频 1 概述 - 2 javadoc标签 - 3 文档注释 - 4 javadoc输出什么 - 请参照如上章节导航进行阅读 1.概述 Java 支持三种注释方式.前两种分别是 // 和 /* */,第三种被称作说明注释,它以 /** 开始,以 */ 结束. 说明注释允许你在程序中嵌入关于程序的信息.你可以使用 java

Java入门 - 高级教程 - 05.网络编程

原文地址:http://www.work100.net/training/java-networking.html更多教程:光束云 - 免费课程 网络编程 序号 文内章节 视频 1 概述 - 2 Socket编程 - 3 ServerSocket类的方法 - 4 Socket类的方法 - 5 InetAddress类的方法 - 6 Socket客户端实例 - 7 Socket服务端实例 - 请参照如上章节导航进行阅读 1.概述 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连

Java入门 - 高级教程 - 02.集合

原文地址:http://www.work100.net/training/java-collection.html 更多教程:光束云 - 免费课程 集合 序号 文内章节 视频 1 概述 2 集合接口 3 集合实现类(集合类) 4 集合算法 5 如何使用迭代器 6 如何使用比较器 7 总结 请参照如上章节导航进行阅读 1.概述 早在 Java 2 中之前,Java 就提供了特设类.比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组. 虽

Java入门 - 高级教程 - 07.多线程

原文地址:http://www.work100.net/training/java-multi-threading.html更多教程:光束云 - 免费课程 多线程 序号 文内章节 视频 1 概述 - 2 一个线程的生命周期 - 3 线程的优先级 - 4 创建一个线程 - 5 通过实现Runnable接口来创建线程 - 6 通过继承Thread来创建线程 - 7 通过继承Thread来创建线程 - 8 通过Callable和Future创建线程 - 9 创建线程的三种方式的对比 - 10 线程的几

Java入门 - 高级教程 - 06.邮件收发

原文地址:http://www.work100.net/training/java-email.html更多教程:光束云 - 免费课程 邮件收发 序号 文内章节 视频 1 概述 - 2 发送一封简单的邮件 - 3 发送一封HTML邮件 - 4 发送带有附件的邮件 - 5 用户认证 - 请参照如上章节导航进行阅读 1.概述 使用Java应用程序发送 E-mail 十分简单,但是首先你应该在你的机器上安装 JavaMail API 和Java Activation Framework (JAF) .

Java入门 - 高级教程 - 08.Applet

原文地址:http://www.work100.net/training/java-applet.html更多教程:光束云 - 免费课程 Applet 序号 文内章节 视频 1 概述 - 2 Applet的生命周期 - 3 一个简单Applet程序 - 4 Applet类 - 5 Applet的调用 - 6 获得Applet参数 - 7 指定Applet参数 - 8 应用程序转换成Applet - 9 事件处理 - 10 显示图片 - 11 播放音频 - 请参照如上章节导航进行阅读 1.概述 A

Java入门学习教程视频

对于Java入门基础学习是必要,特别面向对象的学习,是基础也是掌握Java及运用的核心部分! 以下提供两个学习Java入门材料, http://www.jikexueyuan.com/ 极客学院,基础入门的一些知识的实践操作视频教程,简洁易懂 http://www.runoob.com/java/java-tutorial.html Java菜鸟教程,对于java语法了解是很有帮助的 通过以上学习,对Java就也个比较基础认识,也可使用工具进行一些简单编程操作.

java Vamei快速教程04 封装和接口

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 总结之前的内容,对象(object)指代某一事物,类(class)指代象的类型.对象可以有状态和动作,即数据成员和方法. 到现在为止,数据成员和方法都是同时开放给内部和外部的.在对象内部,我们利用this来调用对象的数据成员和方法.在对象外部,比如当我们在另一个类中调用对象的时,可以使用 对象.数据成员 和 对象.方法() 来调用对象的数据成员和方法. 我们将要封装(encaps