JAVA概述
第一部分:java入门基础
第二部分:java常用类
第三部分:jdbc系列教程
第四部分:java高级特征
java8新特征详解
java文件操作专题教程

知识点

相关文章

更多

最近更新

更多

Java序列化

2019-03-28 22:38|来源: 网络

Java序列化

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

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

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

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

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接口。


序列化对象

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


反序列化对象

下面的DeserializeDemo程序反序列化在SerializeDemo程序中创建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。


转自网络  

相关问答

更多
  • 序列化是将变量转换为可保存或传输的字符串的过程;反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。 PHP中的序列化和反序列化分别通过函数serialize()和unserialize()即可实现。serialize()的参数可以是resource类型外的所有变量类型,最常见的是用来序列化对象,unseialize()将serialize的返回结果作为参数,进行反序列化,得到原对象。
  • 理论上可以,不过你的php传过来的数据是怎么序列化的,是用php序列化的? 那需要你自己写规则和php的序列化对应的反序列化。
  • proxy对象是不能序列化的,就算能序列化也不能反序列化,因为proxy对象的类是动态生成出来的,序列化后,反序列化时目标jVM肯定没有加载过这个代理类。 有个变通的方法,就是获取到对象本身,序列化;反序列化后获取到原对象,再重新用代理包装即可获得反序列化后的代理对象了。不知道是否贴题。下面有个例子,虽然没有序列化和反序列化,但是基本实现了获取对象本身这个功能,希望能帮到你。 另外groovy对象也是java对象,应该仍然保持groovy对象本身(个人理解,groovy我也是略懂皮毛),spring应该不会 ...
  • 准备工作和类设计 1 启动VS,新建C# 类库项目,并命名为KTools。 2 添加C# Winform项目,命名为Test,重命名主窗口为MainForm,并设置为启动项。同时在KTools项目添加文件夹Serializer,并在该文件夹中添加3个类:XMLSerializer、SoapSerializer和BinarySerializer,如下图: 3 该类库的设计目标是快速方便,最好把序列化和反序列化的方法做成静态方法,这样就可以省去了实例化的步骤。序列化大体上分为序列化到文件和序列化到流,虽然序列化 ...
  • 正如其他人所说,Josh Bloch的“ 有效Java”第11章是Java Serialization不可或缺的资源。 从这一章的几点与你的问题有关: 假设您要序列化MyClass2中不可序列化字段的状态,该字段必须直接或通过getter和setter才能访问MyClass。 MyClass将通过提供readObject和writeObject方法来实现自定义序列化。 不可序列化字段的Class必须具有一个API,以允许获取其状态(用于写入对象流),然后使用该状态实例化一个新实例(稍后从对象流读取)。 有效 ...
  • 现在的“官方”Java API现在是JAXB - 用于XML绑定的Java API。 请参阅Oracle教程 。 参考实现生活在http://jaxb.java.net/ 2008 Answer The "Official" Java API for this is now JAXB - Java API for XML Binding. See Tutorial by Oracle. The reference implementation lives at http://jaxb.java.net/ 2 ...
  • 我在这里看到3个选项。 我建议选项1,Protobufs。 看看Google的ProtoBufs 或者一些等价物。 这是Java版本。 这是一个C#端口。 Protobufs意味着这种语言交互。 它的二进制,小型,快速和语言不可知的。 它也具有向后兼容性,所以如果将来更改序列化对象,您仍然可以阅读它们。 这个特性对你来说也是透明的,只要你编写代码,理解更新的变量在反序列化旧对象时可能会丢失。 这是一个巨大的优势! 在另一种语言中实现一种语言的默认序列化 您可以尝试在C#中实现Java序列化逻辑,或者在Jav ...
  • 除了你提到的基本步骤外,没有什么需要使对象成为可序列化的。 对于某种形式的getter / setter或构造函数的存在没有要求(尽管可能有其他合理的理由要求这些)。 There is nothing required to make an Object serializable, apart from the basic steps you've mentioned. There are no requirements for the existence of getters/setters or con ...
  • 你可以试试Avro: http://avro.apache.org/ Avro provides: * Rich data structures. * A compact, fast, binary data format. * A container file, to store persistent data. * Remote procedure call (RPC). * Simple integration with dynamic languages. Code generatio ...
  • Java序列化允许通过提供readObject和writeObject方法来自定义串行表单。 与ObjectInputStream.readFields , ObjectOutputStrean.putFields和定义serialPersistentFields ,序列化表单可以与实现类中的实际字段无关。 但是,Java序列化会产生不透明的数据,这些数据不适合通过其他技术进行读写。 Java serialisation allows customising of the serial form by pr ...